feat(theme): add ThemeAccents struct + accents_for() lookup
This commit is contained in:
parent
4effd7b061
commit
ee1a02e20d
1 changed files with 79 additions and 0 deletions
79
src/theme.rs
79
src/theme.rs
|
|
@ -10,6 +10,58 @@ pub const THEMES: &[(&str, &str)] = &[
|
||||||
("emo-scene-queen", "Emo: Scene Queen"),
|
("emo-scene-queen", "Emo: Scene Queen"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// Theme-aware semantic accent colors. egui `Visuals` has no slot for these,
|
||||||
|
/// so each theme exposes them here and the paint code in `app.rs` reads from
|
||||||
|
/// the active snapshot instead of hardcoding RGB values.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
|
pub struct ThemeAccents {
|
||||||
|
/// Selection / focus ring (replaces the hardcoded 120,170,230 blue).
|
||||||
|
pub accent: Color32,
|
||||||
|
/// Playing / watched indicator (replaces 110,200,110 green).
|
||||||
|
pub success: Color32,
|
||||||
|
/// Bulk-selection highlight (replaces 180,130,240 purple).
|
||||||
|
pub warning: Color32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ThemeAccents {
|
||||||
|
/// The stock fallback used before theme-specific accents are wired in.
|
||||||
|
/// Matches the legacy hardcoded values so behavior is unchanged when a
|
||||||
|
/// theme has not yet defined its own.
|
||||||
|
pub const LEGACY: ThemeAccents = ThemeAccents {
|
||||||
|
accent: Color32::from_rgb(120, 170, 230),
|
||||||
|
success: Color32::from_rgb(110, 200, 110),
|
||||||
|
warning: Color32::from_rgb(180, 130, 240),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Look up the semantic accents for a theme name. Falls back to the dark
|
||||||
|
/// theme's accents for unknown names.
|
||||||
|
pub fn accents_for(name: &str) -> ThemeAccents {
|
||||||
|
match name {
|
||||||
|
"dark" => ThemeAccents { accent: hex(0x7aa2f7), success: hex(0x9ece6a), warning: hex(0xbb9af7) },
|
||||||
|
"light" => ThemeAccents { accent: hex(0x2a5db0), success: hex(0x2e7d32), warning: hex(0x8e44ad) },
|
||||||
|
"dracula" => ThemeAccents { accent: hex(0xbd93f9), success: hex(0x50fa7b), warning: hex(0xff79c6) },
|
||||||
|
"trans" => ThemeAccents { accent: hex(0x55cdfc), success: hex(0x2e7d32), warning: hex(0xf7a8b8) },
|
||||||
|
"emo-nocturnal" => ThemeAccents { accent: hex(0xff0090), success: hex(0x39ff14), warning: hex(0x00f5ff) },
|
||||||
|
"emo-coffin" => ThemeAccents { accent: hex(0x8b0000), success: hex(0x39ff14), warning: hex(0xcc2222) },
|
||||||
|
"emo-scene-queen" => ThemeAccents { accent: hex(0x39ff14), success: hex(0xff00ff), warning: hex(0x00f5ff) },
|
||||||
|
// New themes (added in a later task — values match their palettes).
|
||||||
|
"cyberpunk" => ThemeAccents { accent: hex(0x00fff5), success: hex(0x39ff14), warning: hex(0xff003c) },
|
||||||
|
"synthwave" => ThemeAccents { accent: hex(0xff2a6d), success: hex(0x05d9e8), warning: hex(0xd136a6) },
|
||||||
|
"vaporwave" => ThemeAccents { accent: hex(0x01cdfe), success: hex(0x05ffa1), warning: hex(0xff71ce) },
|
||||||
|
"cemetery-moss" => ThemeAccents { accent: hex(0x7a8a6a), success: hex(0x4a5d3a), warning: hex(0x9a9a8a) },
|
||||||
|
"vampire" => ThemeAccents { accent: hex(0xc9a227), success: hex(0x8b1a2b), warning: hex(0x5c0a1e) },
|
||||||
|
"witching-hour" => ThemeAccents { accent: hex(0x6a4a8b), success: hex(0xb0b8d0), warning: hex(0x1a1a4a) },
|
||||||
|
"nord" => ThemeAccents { accent: hex(0x88c0d0), success: hex(0xa3be8c), warning: hex(0xebcb8b) },
|
||||||
|
"gruvbox" => ThemeAccents { accent: hex(0xfe8019), success: hex(0xb8bb26), warning: hex(0xd3869b) },
|
||||||
|
"tokyo-night" => ThemeAccents { accent: hex(0x7aa2f7), success: hex(0x9ece6a), warning: hex(0xbb9af7) },
|
||||||
|
"paper" => ThemeAccents { accent: hex(0x8b6f3a), success: hex(0x4a6b3a), warning: hex(0xc4a86a) },
|
||||||
|
"honey" => ThemeAccents { accent: hex(0xe8a838), success: hex(0xb87420), warning: hex(0xc97b4a) },
|
||||||
|
"candlelight" => ThemeAccents { accent: hex(0xa8703a), success: hex(0x6b3f1e), warning: hex(0xd9b382) },
|
||||||
|
_ => ThemeAccents { accent: hex(0x7aa2f7), success: hex(0x9ece6a), warning: hex(0xbb9af7) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn apply(ctx: &egui::Context, name: &str) {
|
pub fn apply(ctx: &egui::Context, name: &str) {
|
||||||
let visuals = match name {
|
let visuals = match name {
|
||||||
"light" => egui::Visuals::light(),
|
"light" => egui::Visuals::light(),
|
||||||
|
|
@ -192,3 +244,30 @@ fn emo_scene_queen() -> egui::Visuals {
|
||||||
v.error_fg_color = hex(0xff4444);
|
v.error_fg_color = hex(0xff4444);
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn accents_for_known_theme_returns_nonzero() {
|
||||||
|
let a = accents_for("dark");
|
||||||
|
assert_ne!(a.accent, Color32::TRANSPARENT);
|
||||||
|
assert_ne!(a.success, Color32::TRANSPARENT);
|
||||||
|
assert_ne!(a.warning, Color32::TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn accents_for_unknown_theme_falls_back() {
|
||||||
|
let a = accents_for("this-theme-does-not-exist");
|
||||||
|
let dark = accents_for("dark");
|
||||||
|
assert_eq!(a.accent, dark.accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn accents_differ_across_themes() {
|
||||||
|
let dark = accents_for("dark");
|
||||||
|
let light = accents_for("light");
|
||||||
|
assert_ne!(dark.accent, light.accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue