1use std::collections::HashMap;
2
3use thaw_macro::WriteCSSVars;
4
5#[derive(Clone, WriteCSSVars)]
6pub struct ColorTheme {
7 pub color_scheme: String,
8
9 pub color_neutral_background_static: String,
10 pub color_neutral_background_inverted: String,
11 pub color_neutral_background_disabled: String,
12 pub color_neutral_background_1: String,
13 pub color_neutral_background_1_hover: String,
14 pub color_neutral_background_1_pressed: String,
15 pub color_neutral_background_3: String,
16 pub color_neutral_background_3_hover: String,
17 pub color_neutral_background_3_pressed: String,
18 pub color_neutral_background_4: String,
19 pub color_neutral_background_4_hover: String,
20 pub color_neutral_background_4_pressed: String,
21 pub color_neutral_background_5: String,
22 pub color_neutral_background_6: String,
23
24 pub color_neutral_foreground_static_inverted: String,
25 pub color_neutral_foreground_disabled: String,
26 pub color_neutral_foreground_1: String,
27 pub color_neutral_foreground_1_hover: String,
28 pub color_neutral_foreground_1_pressed: String,
29 pub color_neutral_foreground_2: String,
30 pub color_neutral_foreground_2_hover: String,
31 pub color_neutral_foreground_2_pressed: String,
32 pub color_neutral_foreground_2_brand_hover: String,
33 pub color_neutral_foreground_2_brand_pressed: String,
34 pub color_neutral_foreground_2_brand_selected: String,
35 pub color_neutral_foreground_3: String,
36 pub color_neutral_foreground_4: String,
37 pub color_neutral_foreground_on_brand: String,
38 pub color_neutral_foreground_inverted: String,
39
40 pub color_neutral_stroke_disabled: String,
41 pub color_neutral_stroke_1: String,
42 pub color_neutral_stroke_1_hover: String,
43 pub color_neutral_stroke_1_pressed: String,
44 pub color_neutral_stroke_2: String,
45 pub color_neutral_stroke_accessible: String,
46 pub color_neutral_stroke_accessible_hover: String,
47 pub color_neutral_stroke_accessible_pressed: String,
48
49 pub color_neutral_shadow_ambient: String,
50 pub color_neutral_shadow_key: String,
51
52 pub color_neutral_stencil_1: String,
53 pub color_neutral_stencil_2: String,
54
55 pub color_compound_brand_foreground_1: String,
56 pub color_compound_brand_foreground_1_hover: String,
57 pub color_compound_brand_foreground_1_pressed: String,
58 pub color_compound_brand_background: String,
59 pub color_compound_brand_background_hover: String,
60 pub color_compound_brand_background_pressed: String,
61 pub color_compound_brand_stroke: String,
62 pub color_compound_brand_stroke_pressed: String,
63
64 pub color_brand_background: String,
65 pub color_brand_background_hover: String,
66 pub color_brand_background_pressed: String,
67 pub color_brand_background_2: String,
68 pub color_brand_foreground_1: String,
69 pub color_brand_foreground_2: String,
70 pub color_brand_stroke_1: String,
71 pub color_brand_stroke_2: String,
72 pub color_brand_stroke_2_contrast: String,
73 pub color_brand_foreground_link: String,
74 pub color_brand_foreground_link_hover: String,
75 pub color_brand_foreground_link_pressed: String,
76
77 pub color_stroke_focus_2: String,
78
79 pub color_palette_red_background_1: String,
80 pub color_palette_red_background_3: String,
81 pub color_palette_red_foreground_1: String,
82 pub color_palette_red_foreground_3: String,
83 pub color_palette_red_border_1: String,
84 pub color_palette_red_border_2: String,
85 pub color_palette_green_background_1: String,
86 pub color_palette_green_background_3: String,
87 pub color_palette_green_foreground_1: String,
88 pub color_palette_green_foreground_3: String,
89 pub color_palette_green_border_1: String,
90 pub color_palette_green_border_2: String,
91 pub color_palette_yellow_background_1: String,
92 pub color_palette_yellow_background_3: String,
93 pub color_palette_yellow_foreground_1: String,
94 pub color_palette_yellow_foreground_2: String,
95 pub color_palette_yellow_border_1: String,
96
97 pub color_palette_dark_orange_background_1: String,
98 pub color_palette_dark_orange_background_3: String,
99 pub color_palette_dark_orange_foreground_1: String,
100 pub color_palette_dark_orange_foreground_3: String,
101 pub color_palette_dark_orange_border_1: String,
102
103 pub color_status_success_background_1: String,
104 pub color_status_success_foreground_1: String,
105 pub color_status_success_border_1: String,
106 pub color_status_warning_background_1: String,
107 pub color_status_warning_foreground_3: String,
108 pub color_status_warning_border_1: String,
109 pub color_status_danger_background_1: String,
110 pub color_status_danger_foreground_1: String,
111 pub color_status_danger_border_1: String,
112
113 pub color_subtle_background: String,
114 pub color_subtle_background_hover: String,
115 pub color_subtle_background_pressed: String,
116 pub color_transparent_background: String,
117 pub color_transparent_background_hover: String,
118 pub color_transparent_background_pressed: String,
119 pub color_transparent_stroke: String,
120
121 pub shadow4: String,
122 pub shadow8: String,
123 pub shadow16: String,
124 pub shadow64: String,
125}
126
127impl ColorTheme {
128
129 fn validate_palette(brand_colors: &HashMap<i32, &str>) {
130 for v in 1..=16 {
131 let variant = v*10;
132 brand_colors.get(&variant).unwrap_or_else(|| panic!("Missing variant {} in brand color palette", variant));
133 }
134 }
135 pub fn custom_light(brand_colors: &HashMap<i32, &str>) -> Self {
136 Self::validate_palette(brand_colors);
137 let mut theme = Self::light();
138 theme.color_brand_background = brand_colors.get(&80).unwrap().to_string();
139 theme.color_brand_background_2 = brand_colors.get(&160).unwrap().to_string();
140 theme.color_brand_background_hover = brand_colors.get(&70).unwrap().to_string();
141 theme.color_brand_background_pressed = brand_colors.get(&40).unwrap().to_string();
142 theme.color_brand_foreground_1 = brand_colors.get(&80).unwrap().to_string();
143 theme.color_brand_foreground_2 = brand_colors.get(&70).unwrap().to_string();
144 theme.color_brand_foreground_link = brand_colors.get(&70).unwrap().to_string();
145 theme.color_brand_foreground_link_hover = brand_colors.get(&60).unwrap().to_string();
146 theme.color_brand_foreground_link_pressed = brand_colors.get(&40).unwrap().to_string();
147 theme.color_brand_stroke_1 = brand_colors.get(&80).unwrap().to_string();
148 theme.color_brand_stroke_2 = brand_colors.get(&140).unwrap().to_string();
149 theme.color_brand_stroke_2_contrast = brand_colors.get(&140).unwrap().to_string();
150 theme.color_compound_brand_background = brand_colors.get(&80).unwrap().to_string();
151 theme.color_compound_brand_background_hover = brand_colors.get(&70).unwrap().to_string();
152 theme.color_compound_brand_background_pressed = brand_colors.get(&60).unwrap().to_string();
153 theme.color_compound_brand_foreground_1 = brand_colors.get(&80).unwrap().to_string();
154 theme.color_compound_brand_foreground_1_hover = brand_colors.get(&70).unwrap().to_string();
155 theme.color_compound_brand_foreground_1_pressed = brand_colors.get(&60).unwrap().to_string();
156 theme.color_compound_brand_stroke = brand_colors.get(&80).unwrap().to_string();
157 theme.color_compound_brand_stroke_pressed = brand_colors.get(&60).unwrap().to_string();
158 theme.color_neutral_foreground_2_brand_hover = brand_colors.get(&80).unwrap().to_string();
159 theme.color_neutral_foreground_2_brand_pressed = brand_colors.get(&70).unwrap().to_string();
160 theme.color_neutral_foreground_2_brand_selected = brand_colors.get(&80).unwrap().to_string();
161 theme
162 }
163
164 pub fn custom_dark(brand_colors: &HashMap<i32, &str>) -> Self {
165 Self::validate_palette(brand_colors);
166 let mut theme = Self::dark();
167 theme.color_brand_background = brand_colors.get(&70).unwrap().to_string();
168 theme.color_brand_background_2 = brand_colors.get(&20).unwrap().to_string();
169 theme.color_brand_background_hover = brand_colors.get(&80).unwrap().to_string();
170 theme.color_brand_background_pressed = brand_colors.get(&40).unwrap().to_string();
171 theme.color_brand_foreground_1 = brand_colors.get(&110).unwrap().to_string();
172 theme.color_brand_foreground_2 = brand_colors.get(&120).unwrap().to_string();
173 theme.color_brand_foreground_link = brand_colors.get(&100).unwrap().to_string();
174 theme.color_brand_foreground_link_hover = brand_colors.get(&110).unwrap().to_string();
175 theme.color_brand_foreground_link_pressed = brand_colors.get(&90).unwrap().to_string();
176 theme.color_brand_stroke_1 = brand_colors.get(&100).unwrap().to_string();
177 theme.color_brand_stroke_2 = brand_colors.get(&50).unwrap().to_string();
178 theme.color_brand_stroke_2_contrast = brand_colors.get(&50).unwrap().to_string();
179 theme.color_compound_brand_background = brand_colors.get(&100).unwrap().to_string();
180 theme.color_compound_brand_background_hover = brand_colors.get(&110).unwrap().to_string();
181 theme.color_compound_brand_background_pressed = brand_colors.get(&90).unwrap().to_string();
182 theme.color_compound_brand_foreground_1 = brand_colors.get(&100).unwrap().to_string();
183 theme.color_compound_brand_foreground_1_hover = brand_colors.get(&110).unwrap().to_string();
184 theme.color_compound_brand_foreground_1_pressed = brand_colors.get(&90).unwrap().to_string();
185 theme.color_compound_brand_stroke = brand_colors.get(&100).unwrap().to_string();
186 theme.color_compound_brand_stroke_pressed = brand_colors.get(&90).unwrap().to_string();
187 theme.color_neutral_foreground_2_brand_hover = brand_colors.get(&100).unwrap().to_string();
188 theme.color_neutral_foreground_2_brand_pressed = brand_colors.get(&90).unwrap().to_string();
189 theme.color_neutral_foreground_2_brand_selected = brand_colors.get(&100).unwrap().to_string();
190 theme
191 }
192
193 pub fn light() -> Self {
194 Self {
195 color_scheme: "light".into(),
196
197 color_neutral_background_static: "#333333".into(),
198 color_neutral_background_inverted: "#292929".into(),
199 color_neutral_background_disabled: "#f0f0f0".into(),
200 color_neutral_background_1: "#ffffff".into(),
201 color_neutral_background_1_hover: "#f5f5f5".into(),
202 color_neutral_background_1_pressed: "#e0e0e0".into(),
203 color_neutral_background_3: "#f5f5f5".into(),
204 color_neutral_background_3_hover: "#ebebeb".into(),
205 color_neutral_background_3_pressed: "#d6d6d6".into(),
206 color_neutral_background_4: "#f0f0f0".into(),
207 color_neutral_background_4_hover: "#fafafa".into(),
208 color_neutral_background_4_pressed: "#f5f5f5".into(),
209 color_neutral_background_5: "#ebebeb".into(),
210 color_neutral_background_6: "#e6e6e6".into(),
211
212 color_neutral_foreground_static_inverted: "#ffffff".into(),
213 color_neutral_foreground_disabled: "#bdbdbd".into(),
214 color_neutral_foreground_1: "#242424".into(),
215 color_neutral_foreground_1_hover: "#242424".into(),
216 color_neutral_foreground_1_pressed: "#242424".into(),
217 color_neutral_foreground_2: "#424242".into(),
218 color_neutral_foreground_2_hover: "#242424".into(),
219 color_neutral_foreground_2_pressed: "#242424".into(),
220 color_neutral_foreground_2_brand_hover: "#0f6cbd".into(),
221 color_neutral_foreground_2_brand_pressed: "#115ea3".into(),
222 color_neutral_foreground_2_brand_selected: "#0f6cbd".into(),
223 color_neutral_foreground_3: "#616161".into(),
224 color_neutral_foreground_4: "#707070".into(),
225 color_neutral_foreground_on_brand: "#fff".into(),
226 color_neutral_foreground_inverted: "#fff".into(),
227
228 color_neutral_stroke_disabled: "#e0e0e0".into(),
229 color_neutral_stroke_1: "#d1d1d1".into(),
230 color_neutral_stroke_1_hover: "#c7c7c7".into(),
231 color_neutral_stroke_1_pressed: "#b3b3b3".into(),
232 color_neutral_stroke_2: "#e0e0e0".into(),
233 color_neutral_stroke_accessible: "#616161".into(),
234 color_neutral_stroke_accessible_hover: "#575757".into(),
235 color_neutral_stroke_accessible_pressed: "#4d4d4d".into(),
236
237 color_neutral_shadow_ambient: "rgba(0,0,0,0.12)".into(),
238 color_neutral_shadow_key: "rgba(0,0,0,0.14)".into(),
239
240 color_neutral_stencil_1: "#e6e6e6".into(),
241 color_neutral_stencil_2: "#fafafa".into(),
242
243 color_compound_brand_foreground_1: "#0f6cbd".into(),
244 color_compound_brand_foreground_1_hover: "#115ea3".into(),
245 color_compound_brand_foreground_1_pressed: "#0f548c".into(),
246
247 color_compound_brand_background: "#0f6cbd".into(),
248 color_compound_brand_background_hover: "#115ea3".into(),
249 color_compound_brand_background_pressed: "#0f548c".into(),
250 color_compound_brand_stroke: "#0f6cbd".into(),
251 color_compound_brand_stroke_pressed: "#0f548c".into(),
252
253 color_brand_background: "#0f6cbd".into(),
254 color_brand_background_hover: "#115ea3".into(),
255 color_brand_background_pressed: "#0c3b5e".into(),
256 color_brand_background_2: "#ebf3fc".into(),
257 color_brand_foreground_1: "#0f6cbd".into(),
258 color_brand_foreground_2: "#115ea3".into(),
259 color_brand_stroke_1: "#0f6cbd".into(),
260 color_brand_stroke_2: "#b4d6fa".into(),
261 color_brand_stroke_2_contrast: "#b4d6fa".into(),
262 color_brand_foreground_link: "#115ea3".into(),
263 color_brand_foreground_link_hover: "#0f548c".into(),
264 color_brand_foreground_link_pressed: "#0c3b5e".into(),
265
266 color_stroke_focus_2: "#000000".into(),
267
268 color_palette_red_background_1: "#fdf6f6".into(),
269 color_palette_red_background_3: "#d13438".into(),
270 color_palette_red_foreground_1: "#bc2f32".into(),
271 color_palette_red_foreground_3: "#d13438".into(),
272 color_palette_red_border_1: "#f1bbbc".into(),
273 color_palette_red_border_2: "#d13438".into(),
274 color_palette_green_background_1: "#f1faf1".into(),
275 color_palette_green_background_3: "#107c10".into(),
276 color_palette_green_foreground_1: "#0e700e".into(),
277 color_palette_green_foreground_3: "#107c10".into(),
278 color_palette_green_border_1: "#9fd89f".into(),
279 color_palette_green_border_2: "#107c10".into(),
280 color_palette_yellow_background_1: "#fffef5".into(),
281 color_palette_yellow_background_3: "#fde300".into(),
282 color_palette_yellow_foreground_1: "#817400".into(),
283 color_palette_yellow_foreground_2: "#817400".into(),
284 color_palette_yellow_border_1: "#fef7b2".into(),
285
286 color_palette_dark_orange_background_1: "#fdf6f3".into(),
287 color_palette_dark_orange_background_3: "#da3b01".into(),
288 color_palette_dark_orange_foreground_1: "#c43501".into(),
289 color_palette_dark_orange_foreground_3: "#da3b01".into(),
290 color_palette_dark_orange_border_1: "#f4bfab".into(),
291
292 color_status_success_background_1: "#f1faf1".into(),
293 color_status_success_foreground_1: "#0e700e".into(),
294 color_status_success_border_1: "#9fd89f".into(),
295 color_status_warning_background_1: "#fff9f5".into(),
296 color_status_warning_foreground_3: "#bc4b09".into(),
297 color_status_warning_border_1: "#fdcfb4".into(),
298 color_status_danger_background_1: "#fdf3f4".into(),
299 color_status_danger_foreground_1: "#b10e1c".into(),
300 color_status_danger_border_1: "#eeacb2".into(),
301
302 color_subtle_background: "transparent".into(),
303 color_subtle_background_hover: "#f5f5f5".into(),
304 color_subtle_background_pressed: "#e0e0e0".into(),
305 color_transparent_background: "transparent".into(),
306 color_transparent_background_hover: "transparent".into(),
307 color_transparent_background_pressed: "transparent".into(),
308 color_transparent_stroke: "transparent".into(),
309
310 shadow4: "0 0 2px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.14)".into(),
311 shadow8: "0 0 2px rgba(0,0,0,0.12), 0 4px 8px rgba(0,0,0,0.14)".into(),
312 shadow16: "0 0 2px rgba(0,0,0,0.12), 0 8px 16px rgba(0,0,0,0.14)".into(),
313 shadow64: "0 0 8px rgba(0,0,0,0.12), 0 32px 64px rgba(0,0,0,0.14)".into(),
314 }
315 }
316
317 pub fn dark() -> Self {
318 Self {
319 color_scheme: "dark".into(),
320
321 color_neutral_background_static: "#3d3d3d".into(),
322 color_neutral_background_inverted: "#ffffff".into(),
323 color_neutral_background_disabled: "#141414".into(),
324 color_neutral_background_1: "#292929".into(),
325 color_neutral_background_1_hover: "#3d3d3d".into(),
326 color_neutral_background_1_pressed: "#1f1f1f".into(),
327 color_neutral_background_3: "#141414".into(),
328 color_neutral_background_3_hover: "#292929".into(),
329 color_neutral_background_3_pressed: "#0a0a0a".into(),
330 color_neutral_background_4: "#0a0a0a".into(),
331 color_neutral_background_4_hover: "#1f1f1f".into(),
332 color_neutral_background_4_pressed: "#000000".into(),
333 color_neutral_background_5: "#000000".into(),
334 color_neutral_background_6: "#333333".into(),
335
336 color_neutral_foreground_static_inverted: "#ffffff".into(),
337 color_neutral_foreground_disabled: "#5c5c5c".into(),
338 color_neutral_foreground_1: "#fff".into(),
339 color_neutral_foreground_1_hover: "#fff".into(),
340 color_neutral_foreground_1_pressed: "#fff".into(),
341 color_neutral_foreground_2: "#d6d6d6".into(),
342 color_neutral_foreground_2_hover: "#fff".into(),
343 color_neutral_foreground_2_pressed: "#fff".into(),
344 color_neutral_foreground_2_brand_hover: "#479ef5".into(),
345 color_neutral_foreground_2_brand_pressed: "#2886de".into(),
346 color_neutral_foreground_2_brand_selected: "#479ef5".into(),
347 color_neutral_foreground_3: "#adadad".into(),
348 color_neutral_foreground_4: "#999999".into(),
349 color_neutral_foreground_on_brand: "#fff".into(),
350 color_neutral_foreground_inverted: "#242424".into(),
351
352 color_neutral_stroke_disabled: "#424242".into(),
353 color_neutral_stroke_1: "#666666".into(),
354 color_neutral_stroke_1_hover: "#757575".into(),
355 color_neutral_stroke_1_pressed: "#6b6b6b".into(),
356 color_neutral_stroke_2: "#525252".into(),
357 color_neutral_stroke_accessible: "#adadad".into(),
358 color_neutral_stroke_accessible_hover: "#bdbdbd".into(),
359 color_neutral_stroke_accessible_pressed: "#b3b3b3".into(),
360
361 color_neutral_shadow_ambient: "rgba(0,0,0,0.24)".into(),
362 color_neutral_shadow_key: "rgba(0,0,0,0.28)".into(),
363
364 color_neutral_stencil_1: "#575757".into(),
365 color_neutral_stencil_2: "#333333".into(),
366
367 color_compound_brand_foreground_1: "#479ef5".into(),
368 color_compound_brand_foreground_1_hover: "#62abf5".into(),
369 color_compound_brand_foreground_1_pressed: "#2886de".into(),
370
371 color_compound_brand_background: "#479ef5".into(),
372 color_compound_brand_background_hover: "#62abf5".into(),
373 color_compound_brand_background_pressed: "#2886de".into(),
374 color_compound_brand_stroke: "#479ef5".into(),
375 color_compound_brand_stroke_pressed: "#2886de".into(),
376
377 color_brand_background: "#115ea3".into(),
378 color_brand_background_hover: "#0f6cbd".into(),
379 color_brand_background_pressed: "#0c3b5e".into(),
380 color_brand_background_2: "#082338".into(),
381 color_brand_foreground_1: "#479ef5".into(),
382 color_brand_foreground_2: "#62abf5".into(),
383 color_brand_stroke_1: "#479ef5".into(),
384 color_brand_stroke_2: "#0e4775".into(),
385 color_brand_stroke_2_contrast: "#0e4775".into(),
386 color_brand_foreground_link: "#479ef5".into(),
387 color_brand_foreground_link_hover: "#62abf5".into(),
388 color_brand_foreground_link_pressed: "#2886de".into(),
389
390 color_stroke_focus_2: "#ffffff".into(),
391
392 color_palette_red_background_1: "#3f1011".into(),
393 color_palette_red_background_3: "#d13438".into(),
394 color_palette_red_foreground_1: "#e37d80".into(),
395 color_palette_red_foreground_3: "#e37d80".into(),
396 color_palette_red_border_1: "#d13438".into(),
397 color_palette_red_border_2: "#e37d80".into(),
398 color_palette_green_background_1: "#052505".into(),
399 color_palette_green_background_3: "#107c10".into(),
400 color_palette_green_foreground_1: "#54b054".into(),
401 color_palette_green_foreground_3: "#9fd89f".into(),
402 color_palette_green_border_1: "#107c10".into(),
403 color_palette_green_border_2: "#9fd89f".into(),
404 color_palette_yellow_background_1: "#4c4400".into(),
405 color_palette_yellow_background_3: "#fde300".into(),
406 color_palette_yellow_foreground_1: "#feee66".into(),
407 color_palette_yellow_foreground_2: "#fef7b2".into(),
408 color_palette_yellow_border_1: "#fde300".into(),
409
410 color_palette_dark_orange_background_1: "#411200".into(),
411 color_palette_dark_orange_background_3: "#da3b01".into(),
412 color_palette_dark_orange_foreground_1: "#e9835e".into(),
413 color_palette_dark_orange_foreground_3: "#e9835e".into(),
414 color_palette_dark_orange_border_1: "#da3b01".into(),
415
416 color_status_success_background_1: "#052505".into(),
417 color_status_success_foreground_1: "#54b054".into(),
418 color_status_success_border_1: "#107c10".into(),
419 color_status_warning_background_1: "#4a1e04".into(),
420 color_status_warning_foreground_3: "#f98845".into(),
421 color_status_warning_border_1: "#f7630c".into(),
422 color_status_danger_background_1: "#3b0509".into(),
423 color_status_danger_foreground_1: "#dc626d".into(),
424 color_status_danger_border_1: "#c50f1f".into(),
425
426 color_subtle_background: "transparent".into(),
427 color_subtle_background_hover: "#383838".into(),
428 color_subtle_background_pressed: "#2e2e2e".into(),
429 color_transparent_background: "transparent".into(),
430 color_transparent_background_hover: "transparent".into(),
431 color_transparent_background_pressed: "transparent".into(),
432 color_transparent_stroke: "transparent".into(),
433
434 shadow4: "0 0 2px rgba(0,0,0,0.24), 0 2px 4px rgba(0,0,0,0.28)".into(),
435 shadow8: "0 0 2px rgba(0,0,0,0.24), 0 4px 8px rgba(0,0,0,0.28)".into(),
436 shadow16: "0 0 2px rgba(0,0,0,0.24), 0 8px 16px rgba(0,0,0,0.28)".into(),
437 shadow64: "0 0 8px rgba(0,0,0,0.24), 0 32px 64px rgba(0,0,0,0.28)".into(),
438 }
439 }
440}