diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-03-29 20:44:34 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-03-29 20:44:34 +0300 |
| commit | 101de0ce453615c809d95175532bcb86f816163a (patch) | |
| tree | 1722c86a0d553b72bff1de08289564ad39ce5fa4 /src/config.rs | |
| parent | bf6b6d779a63d8952d8db0a7de5daa3454984620 (diff) | |
refactor: two-section sidebar with agent detail panel, theme system with 9 built-in themes
sidebar layout:
- top section: workspace list with accent bar, git branch, state dots
- bottom section: agent detail panel sorted by urgency with braille spinners
- active workspace always highlighted (subtle bg in terminal mode, brighter in nav)
- palette-driven colors throughout (no hardcoded colors in ui.rs)
theme system:
- 9 built-in themes: catppuccin (default), tokyo-night, dracula, nord, gruvbox, one-dark, solarized, kanagawa, rose-pine
- config: theme.name selects base, theme.custom overrides individual tokens
- 15 color tokens: accent, surface0/1, overlay0/1, text, subtext0, mauve, green, yellow, red, blue, teal, peach
- legacy ui.accent still works for backward compatibility
infrastructure:
- Palette struct on AppState, ready for future theme system extensions
- git_branch() reads .git/HEAD for branch detection
- PaneDetail struct with urgency sorting for agent panel
- spinner_tick counter for braille animation (~8fps on 60fps render loop)
Diffstat (limited to 'src/config.rs')
| -rw-r--r-- | src/config.rs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs index 88092955..fc26b3a5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,11 +16,52 @@ pub struct ToastConfig { #[serde(default)] pub struct Config { pub onboarding: Option<bool>, + pub theme: ThemeConfig, pub keys: KeysConfig, pub ui: UiConfig, pub advanced: AdvancedConfig, } +/// Theme configuration: pick a built-in or override individual tokens. +/// +/// ```toml +/// [theme] +/// name = "tokyo-night" # built-in: catppuccin, tokyo-night, dracula, nord, etc. +/// +/// [theme.custom] # override individual tokens on top of the base +/// accent = "#f5c2e7" +/// red = "#ff6188" +/// ``` +#[derive(Debug, Default, Deserialize)] +#[serde(default)] +pub struct ThemeConfig { + /// Built-in theme name. Default: "catppuccin". + pub name: Option<String>, + /// Custom overrides — applied on top of the selected base theme. + pub custom: Option<CustomThemeColors>, +} + +/// Per-token color overrides. All fields optional — only set what you want to change. +#[derive(Debug, Default, Deserialize)] +#[serde(default)] +pub struct CustomThemeColors { + pub accent: Option<String>, + pub surface0: Option<String>, + pub surface1: Option<String>, + pub surface_dim: Option<String>, + pub overlay0: Option<String>, + pub overlay1: Option<String>, + pub text: Option<String>, + pub subtext0: Option<String>, + pub mauve: Option<String>, + pub green: Option<String>, + pub yellow: Option<String>, + pub red: Option<String>, + pub blue: Option<String>, + pub teal: Option<String>, + pub peach: Option<String>, +} + #[derive(Debug)] pub struct LoadedConfig { pub config: Config, @@ -939,4 +980,39 @@ allow_nested = true let config: Config = toml::from_str(toml).unwrap(); assert!(config.advanced.allow_nested); } + + #[test] + fn theme_name_parses() { + let toml = r#" +[theme] +name = "dracula" +"#; + let config: Config = toml::from_str(toml).unwrap(); + assert_eq!(config.theme.name.as_deref(), Some("dracula")); + } + + #[test] + fn theme_custom_overrides_parse() { + let toml = r##" +[theme] +name = "nord" + +[theme.custom] +accent = "#ff79c6" +red = "rgb(255, 85, 85)" +"##; + let config: Config = toml::from_str(toml).unwrap(); + assert_eq!(config.theme.name.as_deref(), Some("nord")); + let custom = config.theme.custom.as_ref().unwrap(); + assert_eq!(custom.accent.as_deref(), Some("#ff79c6")); + assert_eq!(custom.red.as_deref(), Some("rgb(255, 85, 85)")); + assert!(custom.green.is_none()); + } + + #[test] + fn theme_defaults_when_missing() { + let config: Config = toml::from_str("").unwrap(); + assert!(config.theme.name.is_none()); + assert!(config.theme.custom.is_none()); + } } |
