1use super::*;
2
3#[derive(Debug, Clone, Copy)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct Theme {
11 pub primary: Color,
13 pub secondary: Color,
15 pub accent: Color,
17 pub text: Color,
19 pub text_dim: Color,
21 pub border: Color,
23 pub bg: Color,
25 pub success: Color,
27 pub warning: Color,
29 pub error: Color,
31 pub selected_bg: Color,
33 pub selected_fg: Color,
35 pub surface: Color,
37 pub surface_hover: Color,
42 pub surface_text: Color,
48 pub is_dark: bool,
50}
51
52impl Theme {
53 pub fn dark() -> Self {
55 Self {
56 primary: Color::Cyan,
57 secondary: Color::Blue,
58 accent: Color::Magenta,
59 text: Color::White,
60 text_dim: Color::Indexed(245),
61 border: Color::Indexed(240),
62 bg: Color::Reset,
63 success: Color::Green,
64 warning: Color::Yellow,
65 error: Color::Red,
66 selected_bg: Color::Cyan,
67 selected_fg: Color::Black,
68 surface: Color::Indexed(236),
69 surface_hover: Color::Indexed(238),
70 surface_text: Color::Indexed(250),
71 is_dark: true,
72 }
73 }
74
75 pub fn light() -> Self {
77 Self {
78 primary: Color::Rgb(37, 99, 235),
79 secondary: Color::Rgb(14, 116, 144),
80 accent: Color::Rgb(147, 51, 234),
81 text: Color::Rgb(15, 23, 42),
82 text_dim: Color::Rgb(100, 116, 139),
83 border: Color::Rgb(203, 213, 225),
84 bg: Color::Rgb(248, 250, 252),
85 success: Color::Rgb(22, 163, 74),
86 warning: Color::Rgb(202, 138, 4),
87 error: Color::Rgb(220, 38, 38),
88 selected_bg: Color::Rgb(37, 99, 235),
89 selected_fg: Color::White,
90 surface: Color::Rgb(241, 245, 249),
91 surface_hover: Color::Rgb(226, 232, 240),
92 surface_text: Color::Rgb(51, 65, 85),
93 is_dark: false,
94 }
95 }
96
97 pub fn builder() -> ThemeBuilder {
110 ThemeBuilder {
111 primary: None,
112 secondary: None,
113 accent: None,
114 text: None,
115 text_dim: None,
116 border: None,
117 bg: None,
118 success: None,
119 warning: None,
120 error: None,
121 selected_bg: None,
122 selected_fg: None,
123 surface: None,
124 surface_hover: None,
125 surface_text: None,
126 is_dark: None,
127 }
128 }
129
130 pub fn dracula() -> Self {
132 Self {
133 primary: Color::Rgb(189, 147, 249),
134 secondary: Color::Rgb(139, 233, 253),
135 accent: Color::Rgb(255, 121, 198),
136 text: Color::Rgb(248, 248, 242),
137 text_dim: Color::Rgb(98, 114, 164),
138 border: Color::Rgb(68, 71, 90),
139 bg: Color::Rgb(40, 42, 54),
140 success: Color::Rgb(80, 250, 123),
141 warning: Color::Rgb(241, 250, 140),
142 error: Color::Rgb(255, 85, 85),
143 selected_bg: Color::Rgb(189, 147, 249),
144 selected_fg: Color::Rgb(40, 42, 54),
145 surface: Color::Rgb(68, 71, 90),
146 surface_hover: Color::Rgb(98, 100, 120),
147 surface_text: Color::Rgb(191, 194, 210),
148 is_dark: true,
149 }
150 }
151
152 pub fn catppuccin() -> Self {
154 Self {
155 primary: Color::Rgb(180, 190, 254),
156 secondary: Color::Rgb(137, 180, 250),
157 accent: Color::Rgb(245, 194, 231),
158 text: Color::Rgb(205, 214, 244),
159 text_dim: Color::Rgb(127, 132, 156),
160 border: Color::Rgb(88, 91, 112),
161 bg: Color::Rgb(30, 30, 46),
162 success: Color::Rgb(166, 227, 161),
163 warning: Color::Rgb(249, 226, 175),
164 error: Color::Rgb(243, 139, 168),
165 selected_bg: Color::Rgb(180, 190, 254),
166 selected_fg: Color::Rgb(30, 30, 46),
167 surface: Color::Rgb(49, 50, 68),
168 surface_hover: Color::Rgb(69, 71, 90),
169 surface_text: Color::Rgb(166, 173, 200),
170 is_dark: true,
171 }
172 }
173
174 pub fn nord() -> Self {
176 Self {
177 primary: Color::Rgb(136, 192, 208),
178 secondary: Color::Rgb(129, 161, 193),
179 accent: Color::Rgb(180, 142, 173),
180 text: Color::Rgb(236, 239, 244),
181 text_dim: Color::Rgb(76, 86, 106),
182 border: Color::Rgb(76, 86, 106),
183 bg: Color::Rgb(46, 52, 64),
184 success: Color::Rgb(163, 190, 140),
185 warning: Color::Rgb(235, 203, 139),
186 error: Color::Rgb(191, 97, 106),
187 selected_bg: Color::Rgb(136, 192, 208),
188 selected_fg: Color::Rgb(46, 52, 64),
189 surface: Color::Rgb(59, 66, 82),
190 surface_hover: Color::Rgb(67, 76, 94),
191 surface_text: Color::Rgb(216, 222, 233),
192 is_dark: true,
193 }
194 }
195
196 pub fn solarized_dark() -> Self {
198 Self {
199 primary: Color::Rgb(38, 139, 210),
200 secondary: Color::Rgb(42, 161, 152),
201 accent: Color::Rgb(211, 54, 130),
202 text: Color::Rgb(131, 148, 150),
203 text_dim: Color::Rgb(88, 110, 117),
204 border: Color::Rgb(88, 110, 117),
205 bg: Color::Rgb(0, 43, 54),
206 success: Color::Rgb(133, 153, 0),
207 warning: Color::Rgb(181, 137, 0),
208 error: Color::Rgb(220, 50, 47),
209 selected_bg: Color::Rgb(38, 139, 210),
210 selected_fg: Color::Rgb(253, 246, 227),
211 surface: Color::Rgb(7, 54, 66),
212 surface_hover: Color::Rgb(23, 72, 85),
213 surface_text: Color::Rgb(147, 161, 161),
214 is_dark: true,
215 }
216 }
217
218 pub fn tokyo_night() -> Self {
220 Self {
221 primary: Color::Rgb(122, 162, 247),
222 secondary: Color::Rgb(125, 207, 255),
223 accent: Color::Rgb(187, 154, 247),
224 text: Color::Rgb(169, 177, 214),
225 text_dim: Color::Rgb(86, 95, 137),
226 border: Color::Rgb(54, 58, 79),
227 bg: Color::Rgb(26, 27, 38),
228 success: Color::Rgb(158, 206, 106),
229 warning: Color::Rgb(224, 175, 104),
230 error: Color::Rgb(247, 118, 142),
231 selected_bg: Color::Rgb(122, 162, 247),
232 selected_fg: Color::Rgb(26, 27, 38),
233 surface: Color::Rgb(36, 40, 59),
234 surface_hover: Color::Rgb(41, 46, 66),
235 surface_text: Color::Rgb(192, 202, 245),
236 is_dark: true,
237 }
238 }
239}
240
241pub struct ThemeBuilder {
243 primary: Option<Color>,
244 secondary: Option<Color>,
245 accent: Option<Color>,
246 text: Option<Color>,
247 text_dim: Option<Color>,
248 border: Option<Color>,
249 bg: Option<Color>,
250 success: Option<Color>,
251 warning: Option<Color>,
252 error: Option<Color>,
253 selected_bg: Option<Color>,
254 selected_fg: Option<Color>,
255 surface: Option<Color>,
256 surface_hover: Option<Color>,
257 surface_text: Option<Color>,
258 is_dark: Option<bool>,
259}
260
261impl ThemeBuilder {
262 pub fn primary(mut self, color: Color) -> Self {
263 self.primary = Some(color);
264 self
265 }
266
267 pub fn secondary(mut self, color: Color) -> Self {
268 self.secondary = Some(color);
269 self
270 }
271
272 pub fn accent(mut self, color: Color) -> Self {
273 self.accent = Some(color);
274 self
275 }
276
277 pub fn text(mut self, color: Color) -> Self {
278 self.text = Some(color);
279 self
280 }
281
282 pub fn text_dim(mut self, color: Color) -> Self {
283 self.text_dim = Some(color);
284 self
285 }
286
287 pub fn border(mut self, color: Color) -> Self {
288 self.border = Some(color);
289 self
290 }
291
292 pub fn bg(mut self, color: Color) -> Self {
293 self.bg = Some(color);
294 self
295 }
296
297 pub fn success(mut self, color: Color) -> Self {
298 self.success = Some(color);
299 self
300 }
301
302 pub fn warning(mut self, color: Color) -> Self {
303 self.warning = Some(color);
304 self
305 }
306
307 pub fn error(mut self, color: Color) -> Self {
308 self.error = Some(color);
309 self
310 }
311
312 pub fn selected_bg(mut self, color: Color) -> Self {
313 self.selected_bg = Some(color);
314 self
315 }
316
317 pub fn selected_fg(mut self, color: Color) -> Self {
318 self.selected_fg = Some(color);
319 self
320 }
321
322 pub fn surface(mut self, color: Color) -> Self {
323 self.surface = Some(color);
324 self
325 }
326
327 pub fn surface_hover(mut self, color: Color) -> Self {
328 self.surface_hover = Some(color);
329 self
330 }
331
332 pub fn surface_text(mut self, color: Color) -> Self {
333 self.surface_text = Some(color);
334 self
335 }
336
337 pub fn is_dark(mut self, is_dark: bool) -> Self {
338 self.is_dark = Some(is_dark);
339 self
340 }
341
342 pub fn build(self) -> Theme {
343 let defaults = Theme::dark();
344 Theme {
345 primary: self.primary.unwrap_or(defaults.primary),
346 secondary: self.secondary.unwrap_or(defaults.secondary),
347 accent: self.accent.unwrap_or(defaults.accent),
348 text: self.text.unwrap_or(defaults.text),
349 text_dim: self.text_dim.unwrap_or(defaults.text_dim),
350 border: self.border.unwrap_or(defaults.border),
351 bg: self.bg.unwrap_or(defaults.bg),
352 success: self.success.unwrap_or(defaults.success),
353 warning: self.warning.unwrap_or(defaults.warning),
354 error: self.error.unwrap_or(defaults.error),
355 selected_bg: self.selected_bg.unwrap_or(defaults.selected_bg),
356 selected_fg: self.selected_fg.unwrap_or(defaults.selected_fg),
357 surface: self.surface.unwrap_or(defaults.surface),
358 surface_hover: self.surface_hover.unwrap_or(defaults.surface_hover),
359 surface_text: self.surface_text.unwrap_or(defaults.surface_text),
360 is_dark: self.is_dark.unwrap_or(defaults.is_dark),
361 }
362 }
363}
364
365impl Default for Theme {
366 fn default() -> Self {
367 Self::dark()
368 }
369}