From db6f301f1301d85ca7a4271363760836f53ac0d0 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 22 Aug 2026 17:18:56 -0400 Subject: feat: add per-mode theme overrides (#2324) * feat: add per-mode theme overrides allow [theme.custom.light] and [theme.custom.dark] blocks so custom overrides can differ per resolved appearance when auto_switch flips. precedence: theme defaults, then [theme.custom], then the block for the active mode. configs without the new blocks resolve unchanged. refs #837 * docs: complete per-mode theme documentation --------- Co-authored-by: Ogulcan Celik --- src/config/theme.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'src/config') diff --git a/src/config/theme.rs b/src/config/theme.rs index 8f28390c..cb9e3498 100644 --- a/src/config/theme.rs +++ b/src/config/theme.rs @@ -119,6 +119,35 @@ pub struct CustomThemeColors { pub blue: Option, pub teal: Option, pub peach: Option, + /// Overrides applied when `auto_switch` selects a light appearance. + pub light: Option, + /// Overrides applied when `auto_switch` selects a dark appearance. + pub dark: Option, +} + +/// Per-token color overrides for one auto-switch appearance. +#[derive(Debug, Clone, Default, Deserialize)] +#[serde(default)] +pub struct ModeThemeColors { + pub accent: Option, + pub panel_bg: Option, + pub sidebar_bg: Option, + pub active_row_bg: Option, + pub selection_bg: Option, + pub surface0: Option, + pub surface1: Option, + pub surface_dim: Option, + pub overlay0: Option, + pub overlay1: Option, + pub text: Option, + pub subtext0: Option, + pub mauve: Option, + pub green: Option, + pub yellow: Option, + pub red: Option, + pub blue: Option, + pub teal: Option, + pub peach: Option, } /// Parse a color string into a ratatui Color. @@ -283,6 +312,35 @@ red = "rgb(255, 85, 85)" assert!(custom.green.is_none()); } + #[test] + fn theme_custom_mode_overrides_parse() { + let toml = r##" +[theme.custom] +accent = "#010203" + +[theme.custom.light] +accent = "#040506" +text = "#070809" +selection_bg = "#101112" + +[theme.custom.dark] +panel_bg = "#0a0b0c" +sidebar_bg = "#0d0e0f" +active_row_bg = "#131415" +"##; + let config: Config = toml::from_str(toml).unwrap(); + let custom = config.theme.custom.as_ref().unwrap(); + assert_eq!(custom.accent.as_deref(), Some("#010203")); + let light = custom.light.as_ref().unwrap(); + assert_eq!(light.accent.as_deref(), Some("#040506")); + assert_eq!(light.text.as_deref(), Some("#070809")); + assert_eq!(light.selection_bg.as_deref(), Some("#101112")); + let dark = custom.dark.as_ref().unwrap(); + assert_eq!(dark.panel_bg.as_deref(), Some("#0a0b0c")); + assert_eq!(dark.sidebar_bg.as_deref(), Some("#0d0e0f")); + assert_eq!(dark.active_row_bg.as_deref(), Some("#131415")); + } + #[test] fn theme_defaults_when_missing() { let config: Config = toml::from_str("").unwrap(); -- cgit v1.2.3