1use std::fmt::Display;
2
3use palette::{IntoColor, Oklch, Srgb};
4use serde::{Deserialize, Serialize};
5
6use crate::theme::{Color, ThemeType};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct Theme {
23 pub primary: Color,
24 pub secondary: Color,
25
26 pub background: Color,
27 pub surface: Color,
28 pub border: Color,
29
30 pub foreground: Color,
31 pub muted: Color,
32
33 pub success: Color,
34 pub warning: Color,
35 pub error: Color,
36}
37
38impl Theme {
39 pub fn generate(theme_type: ThemeType, rgb: (u8, u8, u8)) -> Self {
45 match theme_type {
46 ThemeType::Dark => Self::dark(rgb),
47 ThemeType::Light => Self::light(rgb),
48 }
49 }
50
51 pub fn dark((r, g, b): (u8, u8, u8)) -> Self {
56 let color: Oklch =
57 Srgb::new(r as f32 / 255., g as f32 / 255., b as f32 / 255.)
58 .into_color();
59
60 let (secondary, success, warning, error) = Self::shared_colors(color);
61 Self {
62 primary: Color(color),
63 secondary: Color(secondary),
64 background: Color(Oklch::new(0.20, 0.006, color.hue)),
65 surface: Color(Oklch::new(0.25, 0.008, color.hue)),
66 border: Color(Oklch::new(0.32, 0.010, color.hue)),
67 foreground: Color(Oklch::new(0.9, 0.01, color.hue)),
68 muted: Color(Oklch::new(0.65, 0.02, color.hue)),
69 success: Color(success),
70 warning: Color(warning),
71 error: Color(error),
72 }
73 }
74
75 pub fn light((r, g, b): (u8, u8, u8)) -> Self {
81 let mut color: Oklch =
82 Srgb::new(r as f32 / 255., g as f32 / 255., b as f32 / 255.)
83 .into_color();
84
85 color.l = color.l.min(0.70);
86 let (secondary, success, warning, error) = Self::shared_colors(color);
87 Self {
88 primary: Color(color),
89 secondary: Color(secondary),
90 background: Color(Oklch::new(0.98, 0.004, color.hue)),
91 surface: Color(Oklch::new(0.94, 0.006, color.hue)),
92 border: Color(Oklch::new(0.85, 0.010, color.hue)),
93 foreground: Color(Oklch::new(0.15, 0.01, color.hue)),
94 muted: Color(Oklch::new(0.45, 0.02, color.hue)),
95 success: Color(success),
96 warning: Color(warning),
97 error: Color(error),
98 }
99 }
100
101 fn shared_colors(color: Oklch) -> (Oklch, Oklch, Oklch, Oklch) {
102 let mut secondary = color;
103 secondary.hue += 35.;
104
105 let mut success = color;
106 success.hue = 140.0.into();
107
108 let mut warning = color;
109 warning.hue = 100.0.into();
110
111 let mut error = color;
112 error.hue = 25.0.into();
113
114 (secondary, success, warning, error)
115 }
116}
117
118impl Display for Theme {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 writeln!(f, "Primary: {} \x1b[0m", self.primary)?;
121 writeln!(f, "Secondary: {} \x1b[0m", self.secondary)?;
122 writeln!(f, "Background: {} \x1b[0m", self.background)?;
123 writeln!(f, "Surface: {} \x1b[0m", self.surface)?;
124 writeln!(f, "Border: {} \x1b[0m", self.border)?;
125 writeln!(f, "Foreground: {} \x1b[0m", self.foreground)?;
126 writeln!(f, "Muted: {} \x1b[0m", self.muted)?;
127 writeln!(f, "Success: {} \x1b[0m", self.success)?;
128 writeln!(f, "Warning: {} \x1b[0m", self.warning)?;
129 write!(f, "Error: {} \x1b[0m", self.error)
130 }
131}