fast_rich/
theme.rs

1//! Theme system for consistent styling.
2//!
3//! Themes provide predefined color palettes and style configurations.
4
5use crate::style::{Color, Style};
6use std::collections::HashMap;
7
8/// A theme defines colors and styles for different semantic elements.
9#[derive(Debug, Clone)]
10pub struct Theme {
11    /// Primary color
12    pub primary: Color,
13    /// Secondary color
14    pub secondary: Color,
15    /// Success/positive color
16    pub success: Color,
17    /// Warning color
18    pub warning: Color,
19    /// Error/danger color
20    pub error: Color,
21    /// Info color
22    pub info: Color,
23    /// Muted/dim color
24    pub muted: Color,
25    /// Custom named colors
26    pub custom: HashMap<String, Color>,
27}
28
29impl Theme {
30    /// Create a new empty theme with defaults.
31    pub fn new() -> Self {
32        Theme {
33            primary: Color::Blue,
34            secondary: Color::Cyan,
35            success: Color::Green,
36            warning: Color::Yellow,
37            error: Color::Red,
38            info: Color::Cyan,
39            muted: Color::BrightBlack,
40            custom: HashMap::new(),
41        }
42    }
43
44    /// Get the default theme (similar to Rich's default).
45    pub fn default_theme() -> Self {
46        let mut theme = Theme::new();
47        theme.primary = Color::BrightBlue;
48        theme.secondary = Color::Magenta;
49        theme.success = Color::BrightGreen;
50        theme.warning = Color::BrightYellow;
51        theme.error = Color::BrightRed;
52        theme.info = Color::BrightCyan;
53        theme.muted = Color::BrightBlack;
54        theme
55    }
56
57    /// Monokai-inspired theme.
58    pub fn monokai() -> Self {
59        Theme {
60            primary: Color::rgb(102, 217, 239),  // Cyan
61            secondary: Color::rgb(249, 38, 114), // Pink
62            success: Color::rgb(166, 226, 46),   // Green
63            warning: Color::rgb(253, 151, 31),   // Orange
64            error: Color::rgb(249, 38, 114),     // Pink
65            info: Color::rgb(174, 129, 255),     // Purple
66            muted: Color::rgb(117, 113, 94),     // Gray
67            custom: HashMap::new(),
68        }
69    }
70
71    /// Night Owl theme.
72    pub fn night_owl() -> Self {
73        Theme {
74            primary: Color::rgb(130, 170, 255),   // Blue
75            secondary: Color::rgb(199, 146, 234), // Purple
76            success: Color::rgb(173, 219, 103),   // Green
77            warning: Color::rgb(255, 203, 107),   // Yellow
78            error: Color::rgb(239, 83, 80),       // Red
79            info: Color::rgb(128, 203, 196),      // Teal
80            muted: Color::rgb(99, 119, 119),      // Gray
81            custom: HashMap::new(),
82        }
83    }
84
85    /// Get a style for a semantic element.
86    pub fn get_style(&self, name: &str) -> Style {
87        let color = match name {
88            "primary" => self.primary,
89            "secondary" => self.secondary,
90            "success" => self.success,
91            "warning" => self.warning,
92            "error" => self.error,
93            "info" => self.info,
94            "muted" => self.muted,
95            _ => self.custom.get(name).copied().unwrap_or(Color::Default),
96        };
97        Style::new().foreground(color)
98    }
99
100    /// Add a custom color to the theme.
101    pub fn add_color(&mut self, name: impl Into<String>, color: Color) {
102        self.custom.insert(name.into(), color);
103    }
104}
105
106impl Default for Theme {
107    fn default() -> Self {
108        Theme::default_theme()
109    }
110}