Add resolved appearance engine and paired theme settings
Resolve light, dark and automatic appearance centrally and publish live theme snapshots to native surfaces and the appearance portal. Add paired preset families, custom theme imports, accessibility transforms and contrast-safe transitions. Refine the Settings gallery and Auto controls, move overrides under advanced customization, and share palette-aware switches and circular slider thumbs. Document configuration and include theme licenses and integration coverage.
This commit is contained in:
1 parent
2bb4c086f5
commit
3d950a0411
58 files changed
+5556
-644
No files matched your search
+26
-5
@@ -108,22 +108,43 @@ Changing default width preserves manually resized columns.
|
||||
|
||||
## Appearance
|
||||
|
||||
Settings → Appearance offers six presets: **Ferese Blue** (default),
|
||||
**Monochrome**, **Gruvbox**, **Dracula**, **Ayu Light**, and **Monokai**.
|
||||
Ferese Blue uses the logo accent, `#3D7BE6`. Presets update colors and preserve
|
||||
wallpaper, fonts, corners, and opacity. Colors remain individually editable.
|
||||
Settings → Appearance offers six paired themes: **Ferese Blue** (default),
|
||||
**Catppuccin**, **Gruvbox**, **Rosé Pine**, **Tokyo Night**, and **Everforest**.
|
||||
Ferese Blue uses the logo accent, `#3D7BE6`, and has light and dark variants.
|
||||
Choose Light, Dark, or Auto in Settings or Control Center. Auto follows local
|
||||
07:00 and 19:00 boundaries unless you change its schedule.
|
||||
|
||||
Selections store preset names. Partial KDL files can override shared colors or
|
||||
one appearance. See [Themes](theme-engine.md) for files, accessibility options,
|
||||
and live previews.
|
||||
|
||||
| Section / key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `theme.mode` | `"light"`, `"dark"`, `"auto"` | `"dark"` | Selected appearance mode |
|
||||
| `theme.family` | family id | `"ferese-blue"` | Paired theme; automatically uses its light or dark variant |
|
||||
| `theme.split` | boolean | `false` | Use separate light/dark families; retains both selections when disabled |
|
||||
| `theme.light.family`, `theme.dark.family` | family id | `"ferese-blue"` | Stored selections used when split is enabled |
|
||||
| `theme.custom-themes.<id>.file` | path | unset | Imported KDL family with explicit light and/or dark sections |
|
||||
| `theme.light.preset` | preset name | `"ferese-blue-light"` | Light palette; see the [preset pairs](theme-engine.md#preset-pairs) |
|
||||
| `theme.dark.preset` | preset name | `"ferese-blue"` | Dark palette |
|
||||
| `theme.file` | path | unset | Shared partial KDL theme |
|
||||
| `theme.light.file`, `theme.dark.file` | path | unset | Partial KDL theme for one appearance |
|
||||
| `theme.accent` | hex color | unset | Accent override, adjusted for readability in each appearance |
|
||||
| `theme.schedule.source` | `"system"`, `"schedule"` | `"schedule"` | Follow GTK/GNOME appearance or a custom schedule; sunrise/sunset is deferred |
|
||||
| `theme.schedule.timezone` | `"system"` or IANA timezone | `"system"` | Auto schedule timezone |
|
||||
| `theme.schedule.light-at`, `theme.schedule.dark-at` | `HH:MM` | `"07:00"`, `"19:00"` | Auto boundaries; times must differ |
|
||||
| `theme.accessibility.increase-contrast` | boolean | `false` | Strengthen text and borders |
|
||||
| `theme.accessibility.reduce-transparency` | boolean | `false` | Solid surfaces; skip background blur |
|
||||
| `appearance.corner-radius` | number ≥ 0 | unset | Legacy fallback for shell radius |
|
||||
| `appearance.inactive-dim.enabled` | boolean | `false` | Dim unfocused windows |
|
||||
| `appearance.inactive-dim.amount` | number 0–1 | `0.15` | Darkening strength |
|
||||
| `appearance.inactive-dim.duration-ms` | number ≥ 0 | `150` | Dimming and focus-ring transition; 0 snaps |
|
||||
| `theme.typography.font-family` | string | system sans-serif | Shell, Settings and overview font |
|
||||
| `theme.typography.font-family` | string | `"Inter"` | Shell, Settings and overview font |
|
||||
| `theme.background.path` | string | bundled Ferese wallpaper | Wallpaper image path; an existing selection overrides the default |
|
||||
| `theme.background.mode` | `"fill"`, `"fit"` | `"fill"` | Crop or letterbox |
|
||||
| `theme.material.style` | `"solid"`, `"translucent"` | `"solid"` | Shell background material |
|
||||
| `theme.material.opacity` | number 0–1 | `0.78` | Shared shell background opacity for bars, menus, popovers, notifications and themed dialogs. Text/icons stay opaque; 0 hides the material. Solid mode is always opaque |
|
||||
| `theme.material.tint-strength` | number 0–1 | Dark `0.5`, light `1` | Color strength over the blurred backdrop |
|
||||
| `theme.material.blur-radius` | number ≥ 0 | `12` | Translucent backdrop blur, capped at 32; 0 disables |
|
||||
|
||||
| `theme.colors` key | Default | Meaning |
|
||||
|
||||
@@ -7,9 +7,10 @@ and defaults.
|
||||
|
||||
## Shared appearance
|
||||
|
||||
The six presets are Ferese Blue, Monochrome, Gruvbox, Dracula, Ayu Light, and
|
||||
Monokai. Ferese Blue uses the logo accent, `#3D7BE6`. Presets change colors while
|
||||
preserving wallpaper, typography, corners, and opacity.
|
||||
The six theme families are Ferese Blue, Catppuccin, Gruvbox, Rosé Pine, Tokyo
|
||||
Night, and Everforest. Each has a paired light and dark palette. Ferese Blue uses the
|
||||
logo accent, `#3D7BE6`. Presets supply colors and materials; explicit wallpaper,
|
||||
typography, geometry, and material overrides remain in place.
|
||||
|
||||
The interface font applies to shell text and native dialogs. Clock and note
|
||||
widgets can override it. Managed-window corners and shell corners are separate
|
||||
@@ -57,6 +58,7 @@ background so the dialog remains usable.
|
||||
| `palette` | Resolve configuration colors and build the native toolkit theme |
|
||||
| `controls` | Surfaces, navigation, text buttons, and input styles |
|
||||
| `menus` | Rows, headings, sections, separators, switches, and sliders |
|
||||
| `gallery` | Split theme previews, selected badges and accessible radio navigation |
|
||||
| `calendar` | Date/time labels, clock digits, and calendar grids |
|
||||
| `icons` | Shared SVG assets, sizing, and tint |
|
||||
| `typography` | Shared font selection and text |
|
||||
@@ -69,7 +71,7 @@ fonts, foreground colors, or opacity values.
|
||||
|
||||
## UI checks
|
||||
|
||||
- Check text and icons in all six presets, including Ayu Light.
|
||||
- Check text and icons in all twelve light and dark variants.
|
||||
- Check rest, hover, pressed, focused, selected, and disabled controls.
|
||||
- Keep accent-button labels readable after typing or changing focus.
|
||||
- Keep controls usable with solid materials and blur disabled.
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
# Themes
|
||||
|
||||
The compositor resolves theme files and publishes a versioned snapshot. Native
|
||||
apps consume that snapshot; Settings edits references and requests isolated previews.
|
||||
|
||||
## Preset pairs
|
||||
|
||||
| Family | Dark preset | Light preset |
|
||||
| --- | --- | --- |
|
||||
| Ferese Blue (default) | `ferese-blue` | `ferese-blue-light` |
|
||||
| Catppuccin | `catppuccin-mocha` | `catppuccin-latte` |
|
||||
| Gruvbox | `gruvbox` | `gruvbox-light` |
|
||||
| Rosé Pine | `rose-pine-moon` | `rose-pine-dawn` |
|
||||
| Tokyo Night | `tokyo-night` | `tokyo-night-day` |
|
||||
| Everforest | `everforest-dark` | `everforest-light` |
|
||||
|
||||
Each variant supplies its own surfaces, tint strength, opacity, blur, borders,
|
||||
and shadows. Shared material overrides apply to both appearances; appearance
|
||||
specific overrides take precedence. [Palette sources and adjustments](theme-palette-sources.md)
|
||||
record the upstream colors and contrast tuning.
|
||||
|
||||
## Configuration
|
||||
|
||||
```kdl
|
||||
theme {
|
||||
mode "auto"
|
||||
family "catppuccin"
|
||||
split #false
|
||||
file "themes/custom_theme.kdl"
|
||||
light {
|
||||
preset "ferese-blue-light"
|
||||
file "themes/custom_theme_light.kdl"
|
||||
material { opacity 0.94; tint-strength 1; }
|
||||
}
|
||||
dark { preset "ferese-blue"; file "themes/custom_theme_dark.kdl"; }
|
||||
schedule { source "schedule"; timezone "system"; light-at "07:00"; dark-at "19:00"; }
|
||||
accessibility { increase-contrast #false; reduce-transparency #false; }
|
||||
accent "#3D7BE6"
|
||||
}
|
||||
```
|
||||
|
||||
Paths are relative to the configuration directory. Partial theme files contain
|
||||
`theme { colors { accent "#3D7BE6"; } }`, or the token sections directly.
|
||||
Merge order is preset, shared file, appearance file, shared inline tokens,
|
||||
appearance inline tokens, then accent and accessibility adjustments. Unknown tokens warn; invalid known values reject
|
||||
an entire update and retain the last working snapshot.
|
||||
|
||||
## Snapshot
|
||||
|
||||
`ResolvedTheme` contains effective appearance and typed colors, surfaces, material,
|
||||
geometry, typography, wallpaper, border paints, and shadow tokens. Base, raised,
|
||||
and application backgrounds are separate colors. Selected mode,
|
||||
accessibility inputs, requested accent, adjusted accent, warnings, schema version,
|
||||
and revision accompany it. Consumers do not infer appearance from brightness.
|
||||
|
||||
Material tokens differ by appearance. Light glass uses full tint strength and
|
||||
0.94 default opacity to stay pale over dark wallpapers; dark glass uses a softer
|
||||
0.5 tint. Shared material overrides apply to both unless the appearance overrides
|
||||
them. Reduce Transparency resolves to solid
|
||||
material with zero blur. Increase Contrast transforms text and border colors.
|
||||
Accents are adjusted against surfaces independently for each appearance, then
|
||||
on-accent text is selected for readability.
|
||||
|
||||
## Scheduling
|
||||
|
||||
Auto selects the most recent light or dark boundary in the configured timezone.
|
||||
The interval is circular, so light may start after dark. Equal boundaries are
|
||||
invalid. Repeated hours use their first occurrence; skipped hours shift forward
|
||||
by the timezone gap. The next transition arms a realtime timer. Resume, timezone
|
||||
replacement, and realtime clock jumps trigger recalculation without polling.
|
||||
|
||||
## Transitions
|
||||
|
||||
Prepare the incoming wallpaper before starting a 250 ms eased transition. Decode
|
||||
or upload failures and a bounded readiness timeout retain the old wallpaper and
|
||||
allow the theme change. Reduced motion switches immediately.
|
||||
|
||||
Surface, tint, border, shadow, and accent colors can transition. Fonts and geometry
|
||||
switch atomically. Foregrounds remain readable across dark and light backdrops. Near the neutral
|
||||
midpoint, the transition temporarily strengthens material tint instead of fading
|
||||
text through the background color. Tests sample primary, muted,
|
||||
and on-accent text throughout the transition. Wallpaper changes use prepared
|
||||
images rather than a placeholder.
|
||||
|
||||
Publish effective appearance at transition start. The portal emits changed
|
||||
`color-scheme`, `accent-color`, `contrast`, and `reduced-motion` values then.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Action |
|
||||
| --- | --- |
|
||||
| `feresectl theme get` | Read the current mode, effective appearance, and colors |
|
||||
| `feresectl theme status` | Read warnings and the last reload error |
|
||||
| `feresectl theme subscribe` | Stream changes as JSON; no polling |
|
||||
| `feresectl theme mode light` | Save Light mode; also accepts `dark` and `auto` |
|
||||
| `feresectl theme preview PATH` | Resolve a candidate config without applying it |
|
||||
|
||||
Settings shows six paired previews, with Light on the left and Dark on the right.
|
||||
Auto uses a switch in the page header. The adjacent button shows its source and,
|
||||
when enabled, the effective appearance. It opens source and schedule controls
|
||||
below the gallery, which can be edited before enabling Auto. Enabling Auto
|
||||
immediately follows the chosen source; disabling it keeps the current appearance.
|
||||
Manual appearance controls are in Control Center. Selecting a family
|
||||
applies the matching variant live and offers Undo for five
|
||||
seconds. Hovering does not change the desktop. Arrow keys navigate the gallery.
|
||||
Enable **Use different themes for light and dark** for two independent galleries.
|
||||
Disabling it uses the active family and retains the stored pair. A missing
|
||||
variant uses Ferese Blue for that appearance and displays a fallback note.
|
||||
|
||||
**Follow system** reads `org.gnome.desktop.interface color-scheme` and monitors
|
||||
changes. `default` and `prefer-light` mean Light; `prefer-dark` means Dark. If the
|
||||
setting is unavailable, Ferese uses Dark and displays a note. This source does
|
||||
not read Ferese's own appearance portal, avoiding a feedback loop. Sunrise/sunset
|
||||
is deferred.
|
||||
|
||||
The gallery’s Import button adds a family to the gallery without selecting it. Give each
|
||||
variant an explicit section; omitted tokens inherit Ferese Blue for that
|
||||
appearance. For example:
|
||||
|
||||
```kdl
|
||||
theme {
|
||||
name "My theme"
|
||||
light { colors { accent "#8F5300"; }; }
|
||||
dark { colors { accent "#CBA6F7"; }; }
|
||||
}
|
||||
```
|
||||
|
||||
Settings stores the file reference under `theme.custom-themes.<id>.file`.
|
||||
The compositor validates it and publishes its palettes alongside built-ins.
|
||||
Omit a variant to make a single-variant family. Token-only partial files remain
|
||||
supported as shared/per-appearance overrides; imports require explicit variants
|
||||
so appearance is never guessed from brightness. Imported and override files
|
||||
reload after a short debounce, including saves that replace the file. Invalid
|
||||
updates retain the last working theme and produce one desktop notification.
|
||||
|
||||
High contrast, Reduce Transparency and Reduce Motion are in Accessibility.
|
||||
Material, accent, font and geometry controls stay visible below the gallery. Theme
|
||||
overrides are under Advanced customization, in one file-picker row with a
|
||||
Shared/Light/Dark selector; each stored
|
||||
reference is retained when selecting another scope. Settings and shell switches
|
||||
share the same palette. Switch and slider thumbs stay circular regardless of
|
||||
shell corner radius.
|
||||
|
||||
When an older config first adopts mode or preset selection, Ferese moves its
|
||||
inline palette into the dark selection and preserves comments. Shared wallpaper,
|
||||
font, and geometry settings continue to apply to both appearances. For a wallpaper
|
||||
pair, set `background { path "..."; }` inside each appearance or its theme file.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Theme palette sources
|
||||
Ferese maps upstream palettes to desktop roles. Materials are authored for Ferese;
|
||||
text and accents have the adjustments below to meet desktop contrast requirements.
|
||||
| Family | Source revision | License |
|
||||
| --- | --- | --- |
|
||||
| catppuccin | [07d02aa110ef](https://github.com/catppuccin/palette/blob/07d02aa110ef9eb7e7427afca5c73ba9cf7f8ebd/palette.json) | MIT |
|
||||
| gruvbox | [ef8864bb42bf](https://github.com/morhetz/gruvbox/blob/ef8864bb42bf244f0295d1c5a403b27e3d139695/colors/gruvbox.vim) | MIT/X11 |
|
||||
| rose-pine | [ff483051a47e](https://github.com/rose-pine/neovim/blob/ff483051a47e27d84bdef47703538df1ed9f4a47/lua/rose-pine/palette.lua) | MIT |
|
||||
| tokyo-night | [cdc07ac78467](https://github.com/folke/tokyonight.nvim/blob/cdc07ac78467a233fd62c493de29a17e0cf2b2b6/extras/kitty/tokyonight_day.conf) | Apache-2.0; palette exports marked MIT |
|
||||
| everforest | [85a86eb62409](https://github.com/sainnhe/everforest/blob/85a86eb62409e3ec88713bff3d1b9d7374e112e4/autoload/everforest.vim) | MIT |
|
||||
|
||||
Tokyo Night Night also uses its [official export](https://github.com/folke/tokyonight.nvim/blob/cdc07ac78467a233fd62c493de29a17e0cf2b2b6/extras/kitty/tokyonight_night.conf).
|
||||
|
||||
## Color adjustments
|
||||
|
||||
| Variant | Token | Upstream | Ferese |
|
||||
| --- | --- | --- | --- |
|
||||
| rose-pine-moon | muted | `#908CAA` | `#918DAA` |
|
||||
| rose-pine-dawn | muted | `#797593` | `#716D89` |
|
||||
| tokyo-night-day | text | `#3760BF` | `#3358B0` |
|
||||
| tokyo-night-day | muted | `#6172B0` | `#4D5A8C` |
|
||||
| tokyo-night-day | accent | `#2E7DE9` | `#2C76DD` |
|
||||
| everforest-light | muted | `#829181` | `#677367` |
|
||||
| everforest-light | accent | `#8DA101` | `#849601` |
|
||||
|
||||
Catppuccin Latte uses upstream subtext1 for muted labels. Gruvbox uses readable
|
||||
foreground shades rather than its comment gray. Rosé Pine uses its subtle role
|
||||
for secondary labels and its love accent in Dawn. Everforest uses the Hard pair.
|
||||
Tokyo Night uses the upstream Night and Day exports.
|
||||
|
||||
License texts are bundled in [assets/themes/licenses](../assets/themes/licenses)
|
||||
and copied into each installed release. Older saved Monochrome, Dracula, Ayu Light,
|
||||
and Monokai selections remain readable, but are absent from the gallery.
|
||||
Reference in new issue
Block a user