1use egui::Color32;
7use serde::{Deserialize, Serialize};
8
9#[derive(Clone, Debug, Serialize, Deserialize)]
22pub struct Theme {
23 pub colors: ColorPalette,
25
26 pub spacing: Spacing,
28
29 pub typography: Typography,
31}
32
33#[derive(Clone, Debug, Serialize, Deserialize)]
36pub struct ColorPalette {
37 pub background: [u8; 3],
39 pub foreground: [u8; 3],
41
42 pub card: [u8; 3],
44 pub card_foreground: [u8; 3],
46
47 pub popover: [u8; 3],
49 pub popover_foreground: [u8; 3],
51
52 pub primary: [u8; 3],
54 pub primary_foreground: [u8; 3],
56
57 pub secondary: [u8; 3],
59 pub secondary_foreground: [u8; 3],
61
62 pub muted: [u8; 3],
64 pub muted_foreground: [u8; 3],
66
67 pub accent: [u8; 3],
69 pub accent_foreground: [u8; 3],
71
72 pub destructive: [u8; 3],
74 pub destructive_foreground: [u8; 3],
76
77 pub border: [u8; 3],
79 pub input: [u8; 3],
81 pub ring: [u8; 3],
83
84 pub chart_1: [u8; 3],
86 pub chart_2: [u8; 3],
88 pub chart_3: [u8; 3],
90 pub chart_4: [u8; 3],
92 pub chart_5: [u8; 3],
94
95 pub hover: [u8; 3],
97 pub focus: [u8; 3],
99
100 pub sidebar: [u8; 3],
102 pub sidebar_foreground: [u8; 3],
104 pub sidebar_primary: [u8; 3],
106 pub sidebar_primary_foreground: [u8; 3],
108 pub sidebar_accent: [u8; 3],
110 pub sidebar_accent_foreground: [u8; 3],
112 pub sidebar_border: [u8; 3],
114 pub sidebar_ring: [u8; 3],
116}
117
118#[derive(Clone, Debug, Serialize, Deserialize)]
120pub struct Spacing {
121 pub xxs: f32,
123 pub xs: f32,
125 pub sm: f32,
127 pub md: f32,
129 pub lg: f32,
131 pub xl: f32,
133 pub xxl: f32,
135
136 pub corner_radius_micro: u8,
138 pub corner_radius_tiny: u8,
140 pub corner_radius_small: u8,
142 pub corner_radius: u8,
144 pub corner_radius_large: u8,
146}
147
148#[derive(Clone, Debug, Serialize, Deserialize)]
153pub struct Typography {
154 pub xxs: f32,
156 pub xs: f32,
158 pub sm: f32,
160 pub base: f32,
162 pub lg: f32,
164 pub xl: f32,
166 pub xxl: f32,
168}
169
170impl Default for Typography {
171 fn default() -> Self {
172 Self {
173 xxs: 10.0,
174 xs: 11.0,
175 sm: 12.0,
176 base: 14.0,
177 lg: 16.0,
178 xl: 18.0,
179 xxl: 24.0,
180 }
181 }
182}
183
184impl Default for Theme {
185 fn default() -> Self {
186 Self::dark()
187 }
188}
189
190impl Theme {
191 #[must_use]
193 pub const fn dark() -> Self {
194 Self {
195 colors: ColorPalette {
196 background: [9, 9, 11], foreground: [250, 250, 250], card: [9, 9, 11], card_foreground: [250, 250, 250], popover: [9, 9, 11], popover_foreground: [250, 250, 250], primary: [250, 250, 250], primary_foreground: [24, 24, 27], secondary: [39, 39, 42], secondary_foreground: [250, 250, 250], muted: [39, 39, 42], muted_foreground: [161, 161, 170], accent: [39, 39, 42], accent_foreground: [250, 250, 250], destructive: [127, 29, 29], destructive_foreground: [250, 250, 250], border: [39, 39, 42], input: [82, 82, 91], ring: [212, 212, 216], chart_1: [59, 130, 246], chart_2: [34, 197, 94], chart_3: [234, 179, 8], chart_4: [168, 85, 247], chart_5: [249, 115, 22], hover: [39, 39, 42], focus: [250, 250, 250], sidebar: [9, 9, 11], sidebar_foreground: [250, 250, 250], sidebar_primary: [250, 250, 250], sidebar_primary_foreground: [24, 24, 27], sidebar_accent: [39, 39, 42], sidebar_accent_foreground: [250, 250, 250], sidebar_border: [39, 39, 42], sidebar_ring: [212, 212, 216], },
243 spacing: Spacing {
244 xxs: 2.0,
245 xs: 4.0,
246 sm: 8.0,
247 md: 16.0,
248 lg: 24.0,
249 xl: 32.0,
250 xxl: 48.0,
251 corner_radius_micro: 2,
252 corner_radius_tiny: 4,
253 corner_radius_small: 8,
254 corner_radius: 12,
255 corner_radius_large: 16,
256 },
257 typography: Typography {
258 xxs: 10.0,
259 xs: 11.0,
260 sm: 12.0,
261 base: 14.0,
262 lg: 16.0,
263 xl: 18.0,
264 xxl: 24.0,
265 },
266 }
267 }
268
269 #[must_use]
271 pub const fn light() -> Self {
272 Self {
273 colors: ColorPalette {
274 background: [255, 255, 255], foreground: [9, 9, 11], card: [255, 255, 255], card_foreground: [9, 9, 11], popover: [255, 255, 255], popover_foreground: [9, 9, 11], primary: [24, 24, 27], primary_foreground: [250, 250, 250], secondary: [244, 244, 245], secondary_foreground: [24, 24, 27], muted: [244, 244, 245], muted_foreground: [113, 113, 122], accent: [244, 244, 245], accent_foreground: [24, 24, 27], destructive: [239, 68, 68], destructive_foreground: [250, 250, 250], border: [228, 228, 231], input: [228, 228, 231], ring: [24, 24, 27], chart_1: [59, 130, 246], chart_2: [34, 197, 94], chart_3: [234, 179, 8], chart_4: [168, 85, 247], chart_5: [249, 115, 22], hover: [244, 244, 245], focus: [24, 24, 27], sidebar: [250, 250, 250], sidebar_foreground: [9, 9, 11], sidebar_primary: [24, 24, 27], sidebar_primary_foreground: [250, 250, 250], sidebar_accent: [244, 244, 245], sidebar_accent_foreground: [24, 24, 27], sidebar_border: [228, 228, 231], sidebar_ring: [24, 24, 27], },
321 spacing: Spacing {
322 xxs: 2.0,
323 xs: 4.0,
324 sm: 8.0,
325 md: 16.0,
326 lg: 24.0,
327 xl: 32.0,
328 xxl: 48.0,
329 corner_radius_micro: 2,
330 corner_radius_tiny: 4,
331 corner_radius_small: 8,
332 corner_radius: 12,
333 corner_radius_large: 16,
334 },
335 typography: Typography {
336 xxs: 10.0,
337 xs: 11.0,
338 sm: 12.0,
339 base: 14.0,
340 lg: 16.0,
341 xl: 18.0,
342 xxl: 24.0,
343 },
344 }
345 }
346
347 #[must_use]
353 pub const fn background(&self) -> Color32 {
354 let [r, g, b] = self.colors.background;
355 Color32::from_rgb(r, g, b)
356 }
357
358 #[must_use]
360 pub const fn foreground(&self) -> Color32 {
361 let [r, g, b] = self.colors.foreground;
362 Color32::from_rgb(r, g, b)
363 }
364
365 #[must_use]
367 pub const fn card(&self) -> Color32 {
368 let [r, g, b] = self.colors.card;
369 Color32::from_rgb(r, g, b)
370 }
371
372 #[must_use]
374 pub const fn card_foreground(&self) -> Color32 {
375 let [r, g, b] = self.colors.card_foreground;
376 Color32::from_rgb(r, g, b)
377 }
378
379 #[must_use]
381 pub const fn popover(&self) -> Color32 {
382 let [r, g, b] = self.colors.popover;
383 Color32::from_rgb(r, g, b)
384 }
385
386 #[must_use]
388 pub const fn popover_foreground(&self) -> Color32 {
389 let [r, g, b] = self.colors.popover_foreground;
390 Color32::from_rgb(r, g, b)
391 }
392
393 #[must_use]
395 pub const fn primary(&self) -> Color32 {
396 let [r, g, b] = self.colors.primary;
397 Color32::from_rgb(r, g, b)
398 }
399
400 #[must_use]
402 pub const fn primary_foreground(&self) -> Color32 {
403 let [r, g, b] = self.colors.primary_foreground;
404 Color32::from_rgb(r, g, b)
405 }
406
407 #[must_use]
409 pub const fn secondary(&self) -> Color32 {
410 let [r, g, b] = self.colors.secondary;
411 Color32::from_rgb(r, g, b)
412 }
413
414 #[must_use]
416 pub const fn secondary_foreground(&self) -> Color32 {
417 let [r, g, b] = self.colors.secondary_foreground;
418 Color32::from_rgb(r, g, b)
419 }
420
421 #[must_use]
423 pub const fn muted(&self) -> Color32 {
424 let [r, g, b] = self.colors.muted;
425 Color32::from_rgb(r, g, b)
426 }
427
428 #[must_use]
430 pub const fn muted_foreground(&self) -> Color32 {
431 let [r, g, b] = self.colors.muted_foreground;
432 Color32::from_rgb(r, g, b)
433 }
434
435 #[must_use]
437 pub const fn accent(&self) -> Color32 {
438 let [r, g, b] = self.colors.accent;
439 Color32::from_rgb(r, g, b)
440 }
441
442 #[must_use]
444 pub const fn accent_foreground(&self) -> Color32 {
445 let [r, g, b] = self.colors.accent_foreground;
446 Color32::from_rgb(r, g, b)
447 }
448
449 #[must_use]
451 pub const fn destructive(&self) -> Color32 {
452 let [r, g, b] = self.colors.destructive;
453 Color32::from_rgb(r, g, b)
454 }
455
456 #[must_use]
458 pub const fn destructive_foreground(&self) -> Color32 {
459 let [r, g, b] = self.colors.destructive_foreground;
460 Color32::from_rgb(r, g, b)
461 }
462
463 #[must_use]
465 pub const fn border(&self) -> Color32 {
466 let [r, g, b] = self.colors.border;
467 Color32::from_rgb(r, g, b)
468 }
469
470 #[must_use]
472 pub const fn input(&self) -> Color32 {
473 let [r, g, b] = self.colors.input;
474 Color32::from_rgb(r, g, b)
475 }
476
477 #[must_use]
479 pub const fn ring(&self) -> Color32 {
480 let [r, g, b] = self.colors.ring;
481 Color32::from_rgb(r, g, b)
482 }
483
484 #[must_use]
486 pub const fn chart_1(&self) -> Color32 {
487 let [r, g, b] = self.colors.chart_1;
488 Color32::from_rgb(r, g, b)
489 }
490
491 #[must_use]
493 pub const fn chart_2(&self) -> Color32 {
494 let [r, g, b] = self.colors.chart_2;
495 Color32::from_rgb(r, g, b)
496 }
497
498 #[must_use]
500 pub const fn chart_3(&self) -> Color32 {
501 let [r, g, b] = self.colors.chart_3;
502 Color32::from_rgb(r, g, b)
503 }
504
505 #[must_use]
507 pub const fn chart_4(&self) -> Color32 {
508 let [r, g, b] = self.colors.chart_4;
509 Color32::from_rgb(r, g, b)
510 }
511
512 #[must_use]
514 pub const fn chart_5(&self) -> Color32 {
515 let [r, g, b] = self.colors.chart_5;
516 Color32::from_rgb(r, g, b)
517 }
518
519 #[must_use]
521 pub const fn hover(&self) -> Color32 {
522 let [r, g, b] = self.colors.hover;
523 Color32::from_rgb(r, g, b)
524 }
525
526 #[must_use]
528 pub const fn focus(&self) -> Color32 {
529 let [r, g, b] = self.colors.focus;
530 Color32::from_rgb(r, g, b)
531 }
532
533 #[must_use]
539 pub const fn sidebar(&self) -> Color32 {
540 let [r, g, b] = self.colors.sidebar;
541 Color32::from_rgb(r, g, b)
542 }
543
544 #[must_use]
546 pub const fn sidebar_foreground(&self) -> Color32 {
547 let [r, g, b] = self.colors.sidebar_foreground;
548 Color32::from_rgb(r, g, b)
549 }
550
551 #[must_use]
553 pub const fn sidebar_primary(&self) -> Color32 {
554 let [r, g, b] = self.colors.sidebar_primary;
555 Color32::from_rgb(r, g, b)
556 }
557
558 #[must_use]
560 pub const fn sidebar_primary_foreground(&self) -> Color32 {
561 let [r, g, b] = self.colors.sidebar_primary_foreground;
562 Color32::from_rgb(r, g, b)
563 }
564
565 #[must_use]
567 pub const fn sidebar_accent(&self) -> Color32 {
568 let [r, g, b] = self.colors.sidebar_accent;
569 Color32::from_rgb(r, g, b)
570 }
571
572 #[must_use]
574 pub const fn sidebar_accent_foreground(&self) -> Color32 {
575 let [r, g, b] = self.colors.sidebar_accent_foreground;
576 Color32::from_rgb(r, g, b)
577 }
578
579 #[must_use]
581 pub const fn sidebar_border(&self) -> Color32 {
582 let [r, g, b] = self.colors.sidebar_border;
583 Color32::from_rgb(r, g, b)
584 }
585
586 #[must_use]
588 pub const fn sidebar_ring(&self) -> Color32 {
589 let [r, g, b] = self.colors.sidebar_ring;
590 Color32::from_rgb(r, g, b)
591 }
592}