From ed0be9726f70a4fb8366a51e2851fc739639e9b8 Mon Sep 17 00:00:00 2001 From: Hugh Kaznowski Date: Sat, 5 Sep 2026 18:40:31 +0100 Subject: [PATCH] Remove duplicate "grey" theme, keep "dark" (ticket 004) "grey" and "dark" rendered identically apart from accent colour, so drop "grey" as a selectable colour scheme everywhere in the frontend (index.css, api.ts's ColorScheme type, the NavMenu picker, the downloadable BUILTIN_THEMES table) and keep "dark" as the single equivalent theme. Existing settings.json files saved with color_scheme: "grey" keep loading correctly: the backend ColorScheme enum aliases the legacy "grey" serde value onto Dark, so old configs transparently migrate to "dark" without any manual intervention. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o --- src/settings.rs | 16 ++++++++++- tickets/004-remove-grey-theme-keep-dark.md | 8 ------ webapp/src/components/NavMenu.tsx | 1 - webapp/src/index.css | 33 +++++----------------- webapp/src/lib/api.ts | 1 - webapp/src/lib/themes.ts | 22 --------------- webapp/src/lib/useSettingsPanel.ts | 2 +- 7 files changed, 23 insertions(+), 60 deletions(-) delete mode 100644 tickets/004-remove-grey-theme-keep-dark.md diff --git a/src/settings.rs b/src/settings.rs index b607019..e492379 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -18,12 +18,17 @@ use crate::alerts::AlertRule; pub type SettingsHandle = Arc>; /// User's preferred colour scheme for the webapp. +/// +/// `Dark` accepts the legacy `"grey"` serde value (ticket 004: "grey" was a +/// near-duplicate of "dark" and has been removed as a selectable option) so a +/// settings file saved before that change still loads cleanly instead of +/// falling back to `System`. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] #[serde(rename_all = "lowercase")] pub enum ColorScheme { Light, + #[serde(alias = "grey")] Dark, - Grey, Red, Green, Blue, @@ -316,6 +321,15 @@ mod tests { assert_eq!(reloaded, settings); } + #[test] + fn legacy_grey_color_scheme_deserializes_as_dark() { + let settings: Settings = serde_json::from_str( + r#"{"color_scheme":"grey","css_entries":[],"custom_theme_id":null,"profiles":{"names":[],"active_profile":null,"profiles_dir":"profiles"},"max_logs":null,"alert_rules":[],"ntfy_topic":null,"ntfy_server":null}"#, + ) + .unwrap(); + assert_eq!(settings.color_scheme, ColorScheme::Dark); + } + #[test] fn round_trips_through_save_and_load() { let dir = tempfile::tempdir().unwrap(); diff --git a/tickets/004-remove-grey-theme-keep-dark.md b/tickets/004-remove-grey-theme-keep-dark.md deleted file mode 100644 index 3ab6137..0000000 --- a/tickets/004-remove-grey-theme-keep-dark.md +++ /dev/null @@ -1,8 +0,0 @@ -# Remove duplicate "grey" theme, keep "dark" - -Dark and grey are the same thing. Keep dark, remove grey. - -## Acceptance criteria -- The "grey" theme option is removed from theme selection UI and settings. -- Any references/config values for "grey" are migrated or aliased to "dark" so existing saved settings don't break. -- "dark" remains as the single equivalent theme. diff --git a/webapp/src/components/NavMenu.tsx b/webapp/src/components/NavMenu.tsx index 7618cad..3f312ee 100644 --- a/webapp/src/components/NavMenu.tsx +++ b/webapp/src/components/NavMenu.tsx @@ -21,7 +21,6 @@ const COLOR_SCHEMES: ColorScheme[] = [ 'system', 'light', 'dark', - 'grey', 'red', 'green', 'blue', diff --git a/webapp/src/index.css b/webapp/src/index.css index 90860de..2df253c 100644 --- a/webapp/src/index.css +++ b/webapp/src/index.css @@ -16,8 +16,13 @@ * so re-declaring the `--c-*` variables under a `html.` selector * re-skins the whole app with no per-component changes. * - * Derivation: `dark`/`grey` share one true black-based neutral (S=0) scale, - * `light` is its exact lightness mirror — these three stay grey throughout. + * Derivation: `dark` uses one true black-based neutral (S=0) scale, `light` + * is its exact lightness mirror — these two stay grey throughout. (There + * used to be a separate `grey` theme sharing `dark`'s neutral scale with + * only its accent trio differing; it was a near-duplicate of `dark` and was + * removed in favour of a single `dark` theme — ticket 004. Settings saved + * with `color_scheme: "grey"` still load fine: the backend aliases it to + * `dark`, see `ColorScheme` in `src/settings.rs`.) * Each named theme (red/green/blue/yellow/pink/orange) instead tints its * whole surface/border/text scale in its own hue at low saturation (so the * chrome itself reads as "a shade of red", not grey-with-a-red-light), and @@ -88,30 +93,6 @@ html.light { --c-accent-text: #0369a1; } -/* Canonical greyscale theme: identical neutral scale to :root (dark), so - every other theme's derivation above is measured against this one. */ -html.grey { - --c-surface-0: #0a0a0a; - --c-surface-1: #171717; - --c-surface-2: #262626; - - --c-border: #262626; - --c-border-soft: #404040; - --c-border-faint: #171717; - --c-border-strong: #a3a3a3; - - --c-text: #f5f5f5; - --c-text-secondary: #d4d4d4; - --c-text-muted: #a3a3a3; - --c-text-subtle: #737373; - --c-text-faint: #525252; - --c-text-faintest: #404040; - - --c-accent: #38bdf8; - --c-accent-soft: #0369a1; - --c-accent-text: #7dd3fc; -} - /* base hue 0 (red): surfaces/borders/text tinted red; accent complement 180 (cyan), accent-soft composite 150 (spring green) */ html.red { diff --git a/webapp/src/lib/api.ts b/webapp/src/lib/api.ts index 91c32ee..a520efc 100644 --- a/webapp/src/lib/api.ts +++ b/webapp/src/lib/api.ts @@ -85,7 +85,6 @@ export type ColorScheme = | 'light' | 'dark' | 'system' - | 'grey' | 'red' | 'green' | 'blue' diff --git a/webapp/src/lib/themes.ts b/webapp/src/lib/themes.ts index 108f4ef..e95d8c2 100644 --- a/webapp/src/lib/themes.ts +++ b/webapp/src/lib/themes.ts @@ -72,28 +72,6 @@ export const BUILTIN_THEMES: Record = { '--c-accent-soft': '#7dd3fc', '--c-accent-text': '#0369a1', }, - grey: { - '--c-surface-0': '#0a0a0a', - '--c-surface-1': '#171717', - '--c-surface-2': '#262626', - '--c-border': '#262626', - '--c-border-soft': '#404040', - '--c-border-faint': '#171717', - '--c-border-strong': '#a3a3a3', - '--c-text': '#f5f5f5', - '--c-text-secondary': '#d4d4d4', - '--c-text-muted': '#a3a3a3', - '--c-text-subtle': '#737373', - '--c-text-faint': '#525252', - '--c-text-faintest': '#404040', - '--c-danger-bg': '#450a0a', - '--c-danger-border': '#7f1d1d', - '--c-danger-text': '#f87171', - '--c-danger-text-strong': '#fca5a5', - '--c-accent': '#38bdf8', - '--c-accent-soft': '#0369a1', - '--c-accent-text': '#7dd3fc', - }, red: { '--c-surface-0': 'hsl(0 32% 10%)', '--c-surface-1': 'hsl(0 28% 16%)', diff --git a/webapp/src/lib/useSettingsPanel.ts b/webapp/src/lib/useSettingsPanel.ts index 1f40976..838efa7 100644 --- a/webapp/src/lib/useSettingsPanel.ts +++ b/webapp/src/lib/useSettingsPanel.ts @@ -24,7 +24,7 @@ const INJECTED_CSS_ATTR = 'data-ottyl-css-id' const INJECTED_THEME_ATTR = 'data-ottyl-theme-css-id' // Themes selectable independently of `system`, each backed by a `html.` block in `index.css`. -const THEME_CLASSES = ['light', 'dark', 'grey', 'red', 'green', 'blue', 'yellow', 'pink', 'orange'] as const +const THEME_CLASSES = ['light', 'dark', 'red', 'green', 'blue', 'yellow', 'pink', 'orange'] as const // Reflects `colorScheme` onto `` as a class + `data-color-scheme`; when a custom theme is active, no built-in class is added at all, since a class selector would out-specificity its injected `:root` override (see `applyCustomThemeCss`) and mask it. function applyColorScheme(colorScheme: ColorScheme, customThemeActive: boolean) {