pelican/theme/
colors.rs

1use roost::drawable::Color;
2
3/// Represents a collection of color resources used throughout the UI, including background, text, button, and status colors.
4#[derive(Clone, Debug, Default, Copy)]
5pub struct ColorResources {
6    /// Defines the background colors.
7    pub background: BackgroundColor,
8    /// Defines the outline colors.
9    pub outline: OutlineColor,
10    /// Defines the colors representing various status indicators.
11    pub status: StatusColor,
12    /// Defines the colors for various text elements.
13    pub text: TextColor,
14    /// Defines the colors for buttons in various states (default, disabled, hover, etc.).
15    pub button: ButtonColors,
16    /// Defines brand-specific colors.
17    pub brand: Color,
18}
19
20impl ColorResources {
21    #[allow(clippy::too_many_arguments)]
22    pub fn new(
23        background: BackgroundColor,
24        outline: OutlineColor,
25        status: StatusColor,
26        text: TextColor,
27        brand: Color,
28        button: ButtonColors,
29    ) -> Self {
30        ColorResources { background, outline, status, text, brand, button }
31    }
32
33    /// Create a light theme from the given primary color.
34    pub fn light(brand: Color) -> Self {
35        ColorResources { 
36            background: BackgroundColor::light(),
37            outline: OutlineColor::light(),
38            status: StatusColor::default(),
39            text: TextColor::light(),
40            brand,
41            button: ButtonColors::from(brand, true),
42        }
43    }
44
45    /// Create a dark theme from the given primary color.
46    pub fn dark(brand: Color) -> Self {
47        ColorResources { 
48            background: BackgroundColor::dark(),
49            outline: OutlineColor::dark(),
50            status: StatusColor::default(),
51            text: TextColor::dark(),
52            brand,
53            button: ButtonColors::from(brand, false),
54        }
55    }
56
57    /// Create a new theme from the brand color.
58    /// Chooses light or dark depending on brightness of the primary color.
59    pub fn from(brand: Color) -> Self {
60        match Color::is_high_contrast(brand) {
61            true => Self::dark(brand),
62            false => Self::light(brand)
63        }
64    }
65}
66
67/// Defines the background colors.   
68#[derive(Copy, Clone, Debug)]
69pub struct BackgroundColor {
70    pub primary: Color,
71    pub secondary: Color,
72}
73
74impl BackgroundColor {
75    pub fn dark() -> Self {
76        BackgroundColor {
77            primary: Color::BLACK,
78            secondary: Color::from_hex("#262322", 255),
79        }
80    }
81    pub fn light() -> Self {
82        BackgroundColor {
83            primary: Color::WHITE,
84            secondary: Color::from_hex("#DDDDDD", 255),
85        }
86    }
87}
88
89impl Default for BackgroundColor {
90    fn default() -> Self { Self::dark() }
91}
92
93/// Defines the outline colors.
94#[derive(Copy, Clone, Debug)]
95pub struct OutlineColor {
96    pub primary: Color,
97    pub secondary: Color,
98}
99
100impl OutlineColor {
101    pub fn dark() -> Self {
102        OutlineColor {
103            primary: Color::WHITE,
104            secondary: Color::from_hex("#585250", 255),
105        }
106    }
107    pub fn light() -> Self {
108        OutlineColor {
109            primary: Color::from_hex("#9e9e9e", 255),
110            secondary: Color::from_hex("#444444", 255),
111        }
112    }
113}
114
115impl Default for OutlineColor {
116    fn default() -> Self { Self::dark() }
117}
118
119/// Defines the colors of text elements.
120#[derive(Copy, Clone, Debug)]
121pub struct TextColor {
122    pub heading: Color,
123    pub primary: Color,
124    pub secondary: Color,
125}
126
127impl TextColor {
128    pub fn dark() -> Self {
129        TextColor {
130            heading: Color::WHITE,
131            primary: Color::from_hex("#e2e1df", 255),
132            secondary: Color::from_hex("#a7a29d", 255),
133        }
134    }
135    pub fn light() -> Self {
136        TextColor {
137            heading: Color::BLACK,
138            primary: Color::BLACK,
139            secondary: Color::from_hex("#9e9e9e", 255),
140        }
141    }
142}
143
144impl Default for TextColor {
145    fn default() -> Self { Self::dark() }
146}
147
148/// Defines the colors representing various status indicators.
149#[derive(Copy, Clone, Debug)]
150pub struct StatusColor {
151    pub success: Color,
152    pub warning: Color,
153    pub danger: Color,
154}
155
156impl Default for StatusColor {
157    fn default() -> Self {
158        StatusColor {
159            success: Color::from_hex("#3ccb5a", 255),
160            warning: Color::from_hex("#f5bd14", 255),
161            danger: Color::from_hex("#ff330a", 255),
162        }
163    }
164}
165
166/// Defines the colors for buttons in various states, including default, disabled, hover, pressed, etc.
167#[derive(Copy, Clone, Debug)]
168pub struct ButtonColors {
169    pub primary: ButtonColorSet,
170    pub secondary: ButtonColorSet,
171    pub ghost: ButtonColorSet,
172}
173
174impl ButtonColors {
175    pub fn from(brand: Color, is_light: bool) -> Self {
176        let label = if is_light {Color::WHITE} else {Color::BLACK};
177        ButtonColors {
178            primary: ButtonColorSet::primary(brand, label),
179            secondary: ButtonColorSet::secondary(is_light),
180            ghost: ButtonColorSet::ghost(is_light),
181        }
182    }
183}
184
185impl Default for ButtonColors {
186    fn default() -> Self {
187        ButtonColors {
188            primary: ButtonColorSet::primary(Color::from_hex("#02f0cc", 255), Color::WHITE),
189            secondary: ButtonColorSet::secondary(false),
190            ghost: ButtonColorSet::ghost(false),
191        }
192    }
193}
194
195/// Defines a color scheme for a button, including background, label, and outline colors.
196#[derive(Copy, Clone, Debug)]
197pub struct ButtonColorScheme {
198    /// The background color of the button.
199    pub background: Color,
200    /// The color of the button label (text).
201    pub label: Color,
202    /// The color of the button outline (border).
203    pub outline: Color,
204}
205
206#[derive(Copy, Clone, Debug)]
207pub struct ButtonColorSet {
208    pub default: ButtonColorScheme,
209    pub disabled: ButtonColorScheme,
210    pub hover: ButtonColorScheme,
211    pub pressed: ButtonColorScheme,
212}
213
214impl ButtonColorSet {
215    pub fn primary(brand: Color, label: Color) -> Self {
216        ButtonColorSet {
217            default: ButtonColorScheme {
218                background: brand,
219                label,
220                outline: Color::TRANSPARENT,
221            },
222            disabled: ButtonColorScheme {
223                background: Color::from_hex("#443f3f", 255),
224                label: Color::BLACK,
225                outline: Color::TRANSPARENT,
226            },
227            hover: ButtonColorScheme {
228                background: Color::darken(brand, 0.85),
229                label,
230                outline: Color::TRANSPARENT,
231            },
232            pressed: ButtonColorScheme {
233                background: Color::darken(brand, 0.8),
234                label,
235                outline: Color::TRANSPARENT
236            }
237        }
238    }
239
240    pub fn secondary(is_light: bool) -> Self {
241        ButtonColorSet {
242            default: ButtonColorScheme {
243                background: Color::TRANSPARENT,
244                label: if is_light {Color::BLACK} else {Color::WHITE},
245                outline: Color::from_hex("#585250", 255),
246            },
247            disabled: ButtonColorScheme {
248                background: Color::from_hex("#78716c", 255),
249                label: Color::BLACK,
250                outline:Color::from_hex("#585250", 255),
251            },
252            hover: ButtonColorScheme {
253                background: if is_light {Color::from_hex("#dcdbda", 255)} else {Color::from_hex("#262322", 255)},
254                label: if is_light {Color::BLACK} else {Color::WHITE},
255                outline: Color::from_hex("#585250", 255),
256            },
257            pressed: ButtonColorScheme {
258                background: if is_light {Color::from_hex("#dcdbda", 255)} else {Color::from_hex("#262322", 255)},
259                label: Color::WHITE,
260                outline: if is_light {Color::BLACK} else {Color::WHITE},
261            }
262        }
263    }
264
265    pub fn ghost(is_light: bool) -> Self {
266        ButtonColorSet {
267            default: ButtonColorScheme {
268                background: Color::TRANSPARENT,
269                label: if is_light {Color::BLACK} else {Color::WHITE},
270                outline: Color::TRANSPARENT,
271            },
272            disabled: ButtonColorScheme {
273                background: Color::TRANSPARENT,
274                label: Color::from_hex("#78716c", 255),
275                outline: Color::TRANSPARENT,
276            },
277            hover: ButtonColorScheme {
278                background: if is_light {Color::from_hex("#dcdbda", 255)} else {Color::from_hex("#262322", 255)},
279                label: if is_light {Color::BLACK} else {Color::WHITE},
280                outline: Color::TRANSPARENT,
281            },
282            pressed: ButtonColorScheme {
283                background: if is_light {Color::from_hex("#dcdbda", 255)} else {Color::from_hex("#262322", 255)},
284                label: if is_light {Color::BLACK} else {Color::WHITE},
285                outline: Color::TRANSPARENT,
286            }
287        }
288    }
289}