1use ratatui::style::{Color, Style, Modifier};
4
5#[derive(Debug, Clone)]
7pub struct Theme {
8 pub name: String,
9
10 pub bg_primary: Color,
12 pub bg_secondary: Color,
13 pub bg_tertiary: Color,
14
15 pub fg_primary: Color,
17 pub fg_secondary: Color,
18 pub fg_dim: Color,
19
20 pub accent: Color,
22 pub success: Color,
23 pub warning: Color,
24 pub error: Color,
25 pub info: Color,
26
27 pub border: Color,
29 pub border_focused: Color,
30 pub selection: Color,
31}
32
33impl Theme {
34 pub fn arc_academy_orange() -> Self {
36 Self {
37 name: "Arc Academy Orange".to_string(),
38
39 bg_primary: Color::Rgb(18, 18, 20), bg_secondary: Color::Rgb(26, 26, 28), bg_tertiary: Color::Rgb(32, 32, 36), fg_primary: Color::Rgb(230, 230, 235), fg_secondary: Color::Rgb(180, 180, 190), fg_dim: Color::Rgb(120, 120, 130), accent: Color::Rgb(255, 107, 53), success: Color::Rgb(80, 200, 120), warning: Color::Rgb(255, 179, 71), error: Color::Rgb(255, 82, 82), info: Color::Rgb(100, 181, 246), border: Color::Rgb(60, 60, 65), border_focused: Color::Rgb(255, 107, 53), selection: Color::Rgb(80, 50, 35), }
58 }
59
60 pub fn arc_academy_green() -> Self {
62 Self {
63 name: "Arc Academy Green".to_string(),
64
65 bg_primary: Color::Rgb(16, 20, 18), bg_secondary: Color::Rgb(22, 27, 24), bg_tertiary: Color::Rgb(28, 34, 30), fg_primary: Color::Rgb(230, 240, 235), fg_secondary: Color::Rgb(180, 200, 190), fg_dim: Color::Rgb(120, 140, 130), accent: Color::Rgb(76, 175, 80), success: Color::Rgb(102, 187, 106), warning: Color::Rgb(255, 193, 7), error: Color::Rgb(244, 67, 54), info: Color::Rgb(41, 182, 246), border: Color::Rgb(50, 65, 55), border_focused: Color::Rgb(76, 175, 80), selection: Color::Rgb(30, 50, 35), }
84 }
85
86 pub fn arc_dark() -> Self {
88 Self {
89 name: "Arc Dark".to_string(),
90
91 bg_primary: Color::Rgb(30, 30, 46), bg_secondary: Color::Rgb(24, 24, 37), bg_tertiary: Color::Rgb(17, 17, 27), fg_primary: Color::Rgb(205, 214, 244), fg_secondary: Color::Rgb(186, 194, 222), fg_dim: Color::Rgb(108, 112, 134), accent: Color::Rgb(137, 180, 250), success: Color::Rgb(166, 227, 161), warning: Color::Rgb(249, 226, 175), error: Color::Rgb(243, 139, 168), info: Color::Rgb(148, 226, 213), border: Color::Rgb(108, 112, 134), border_focused: Color::Rgb(137, 180, 250), selection: Color::Rgb(88, 91, 112), }
110 }
111
112 pub fn arc_light() -> Self {
114 Self {
115 name: "Arc Light".to_string(),
116
117 bg_primary: Color::Rgb(239, 241, 245), bg_secondary: Color::Rgb(230, 233, 239), bg_tertiary: Color::Rgb(220, 224, 232), fg_primary: Color::Rgb(76, 79, 105), fg_secondary: Color::Rgb(92, 95, 119), fg_dim: Color::Rgb(156, 160, 176), accent: Color::Rgb(30, 102, 245), success: Color::Rgb(64, 160, 43), warning: Color::Rgb(223, 142, 29), error: Color::Rgb(210, 15, 57), info: Color::Rgb(4, 165, 229), border: Color::Rgb(156, 160, 176), border_focused: Color::Rgb(30, 102, 245), selection: Color::Rgb(204, 208, 218), }
135 }
136
137 pub fn style_normal(&self) -> Style {
139 Style::default().fg(self.fg_primary).bg(self.bg_primary)
140 }
141
142 pub fn style_secondary(&self) -> Style {
144 Style::default().fg(self.fg_secondary).bg(self.bg_primary)
145 }
146
147 pub fn style_dim(&self) -> Style {
149 Style::default().fg(self.fg_dim).bg(self.bg_primary)
150 }
151
152 pub fn style_header(&self) -> Style {
154 Style::default()
155 .fg(self.fg_primary)
156 .bg(self.bg_secondary)
157 .add_modifier(Modifier::BOLD)
158 }
159
160 pub fn style_border_focused(&self) -> Style {
162 Style::default().fg(self.border_focused)
163 }
164
165 pub fn style_border(&self) -> Style {
167 Style::default().fg(self.border)
168 }
169
170 pub fn style_accent(&self) -> Style {
172 Style::default().fg(self.accent).add_modifier(Modifier::BOLD)
173 }
174
175 pub fn style_success(&self) -> Style {
177 Style::default().fg(self.success)
178 }
179
180 pub fn style_warning(&self) -> Style {
182 Style::default().fg(self.warning).add_modifier(Modifier::BOLD)
183 }
184
185 pub fn style_error(&self) -> Style {
187 Style::default().fg(self.error).add_modifier(Modifier::BOLD)
188 }
189
190 pub fn style_info(&self) -> Style {
192 Style::default().fg(self.info)
193 }
194
195 pub fn style_selection(&self) -> Style {
197 Style::default()
198 .bg(self.selection)
199 .fg(self.fg_primary)
200 }
201
202 pub fn style_block(&self) -> Style {
205 Style::default().bg(self.bg_primary).fg(self.fg_primary)
206 }
207}
208
209impl Default for Theme {
210 fn default() -> Self {
211 Self::arc_academy_orange()
212 }
213}
214
215impl Theme {
216 pub fn cycle_next(&self) -> Self {
218 match self.name.as_str() {
219 "Arc Academy Orange" => Self::arc_academy_green(),
220 "Arc Academy Green" => Self::arc_dark(),
221 "Arc Dark" => Self::arc_light(),
222 _ => Self::arc_academy_orange(),
223 }
224 }
225
226 pub fn from_name(name: &str) -> Self {
228 match name {
229 "Arc Academy Orange" => Self::arc_academy_orange(),
230 "Arc Academy Green" => Self::arc_academy_green(),
231 "Arc Dark" => Self::arc_dark(),
232 "Arc Light" => Self::arc_light(),
233 _ => {
234 tracing::warn!("Unknown theme '{}', using default", name);
235 Self::default()
236 }
237 }
238 }
239}