Skip to main content

freya_components/theming/
themes.rs

1use std::time::Duration;
2
3use freya_core::prelude::*;
4#[cfg(feature = "titlebar")]
5use torin::prelude::Length;
6use torin::{
7    gaps::Gaps,
8    size::Size,
9};
10
11#[cfg(feature = "calendar")]
12use crate::calendar::CalendarThemePreference;
13#[cfg(feature = "router")]
14use crate::link::LinkThemePreference;
15#[cfg(feature = "markdown")]
16use crate::markdown::MarkdownViewerThemePreference;
17#[cfg(feature = "titlebar")]
18use crate::titlebar::TitlebarButtonThemePreference;
19use crate::{
20    accordion::AccordionThemePreference,
21    button::{
22        ButtonColorsThemePreference,
23        ButtonLayoutThemePreference,
24    },
25    card::{
26        CardColorsThemePreference,
27        CardLayoutThemePreference,
28    },
29    checkbox::CheckboxThemePreference,
30    chip::ChipThemePreference,
31    color_picker::ColorPickerThemePreference,
32    floating_tab::FloatingTabThemePreference,
33    input::{
34        InputColorsThemePreference,
35        InputLayoutThemePreference,
36    },
37    loader::CircularLoaderThemePreference,
38    menu::{
39        MenuContainerThemePreference,
40        MenuItemThemePreference,
41    },
42    popup::PopupThemePreference,
43    progressbar::ProgressBarThemePreference,
44    radio_item::RadioItemThemePreference,
45    resizable_container::ResizableHandleThemePreference,
46    scrollviews::ScrollBarThemePreference,
47    segmented_button::{
48        ButtonSegmentThemePreference,
49        SegmentedButtonThemePreference,
50    },
51    select::SelectThemePreference,
52    sidebar::SideBarItemThemePreference,
53    skeleton::{
54        SkeletonAnimation,
55        SkeletonThemePreference,
56    },
57    slider::SliderThemePreference,
58    switch::{
59        SwitchColorsThemePreference,
60        SwitchLayoutThemePreference,
61    },
62    table::TableThemePreference,
63    theming::{
64        component_themes::{
65            ColorsSheet,
66            Theme,
67        },
68        macros::Preference,
69    },
70    tooltip::TooltipThemePreference,
71};
72
73pub const LIGHT_COLORS: ColorsSheet = ColorsSheet {
74    // Brand & Accent
75    primary: Color::from_rgb(103, 80, 164),
76    secondary: Color::from_rgb(202, 193, 227),
77    tertiary: Color::from_rgb(79, 61, 130),
78
79    // Status
80    success: Color::from_rgb(76, 175, 80),
81    warning: Color::from_rgb(255, 193, 7),
82    error: Color::from_rgb(244, 67, 54),
83    info: Color::from_rgb(33, 150, 243),
84
85    // Surfaces
86    background: Color::from_rgb(250, 250, 250),
87    surface_primary: Color::from_rgb(210, 210, 210),
88    surface_secondary: Color::from_rgb(225, 225, 225),
89    surface_tertiary: Color::from_rgb(245, 245, 245),
90    surface_inverse: Color::from_rgb(125, 125, 125),
91    surface_inverse_secondary: Color::from_rgb(110, 110, 110),
92    surface_inverse_tertiary: Color::from_rgb(90, 90, 90),
93
94    // Borders
95    border: Color::from_rgb(210, 210, 210),
96    border_focus: Color::from_rgb(180, 180, 180),
97    border_disabled: Color::from_rgb(210, 210, 210),
98
99    // Text
100    text_primary: Color::from_rgb(10, 10, 10),
101    text_secondary: Color::from_rgb(100, 100, 100),
102    text_placeholder: Color::from_rgb(150, 150, 150),
103    text_inverse: Color::WHITE,
104    text_highlight: Color::from_rgb(38, 89, 170),
105
106    // States
107    focus: Color::from_rgb(225, 225, 255),
108    active: Color::from_rgb(200, 200, 200),
109    disabled: Color::from_rgb(210, 210, 210),
110
111    // Utility
112    overlay: Color::from_af32rgb(0.5, 0, 0, 0),
113    shadow: Color::from_af32rgb(0.2, 0, 0, 0),
114};
115
116pub const DARK_COLORS: ColorsSheet = ColorsSheet {
117    // Brand & Accent
118    primary: Color::from_rgb(103, 80, 164),
119    secondary: Color::from_rgb(202, 193, 227),
120    tertiary: Color::from_rgb(79, 61, 130),
121
122    // Status
123    success: Color::from_rgb(129, 199, 132),
124    warning: Color::from_rgb(255, 213, 79),
125    error: Color::from_rgb(229, 115, 115),
126    info: Color::from_rgb(100, 181, 246),
127
128    // Surfaces
129    background: Color::from_rgb(20, 20, 20),
130    surface_primary: Color::from_rgb(60, 60, 60),
131    surface_secondary: Color::from_rgb(45, 45, 45),
132    surface_tertiary: Color::from_rgb(25, 25, 25),
133    surface_inverse: Color::from_rgb(135, 135, 135),
134    surface_inverse_secondary: Color::from_rgb(150, 150, 150),
135    surface_inverse_tertiary: Color::from_rgb(170, 170, 170),
136
137    // Borders
138    border: Color::from_rgb(60, 60, 60),
139    border_focus: Color::from_rgb(110, 110, 110),
140    border_disabled: Color::from_rgb(80, 80, 80),
141
142    // Text
143    text_primary: Color::from_rgb(250, 250, 250),
144    text_secondary: Color::from_rgb(210, 210, 210),
145    text_placeholder: Color::from_rgb(150, 150, 150),
146    text_inverse: Color::WHITE,
147    text_highlight: Color::from_rgb(96, 145, 224),
148
149    // States
150    focus: Color::from_rgb(100, 100, 120),
151    active: Color::from_rgb(70, 70, 70),
152    disabled: Color::from_rgb(50, 50, 50),
153
154    // Utility
155    overlay: Color::from_af32rgb(0.2, 255, 255, 255),
156    shadow: Color::from_af32rgb(0.6, 0, 0, 0),
157};
158
159fn register_base_component_themes(theme: &mut Theme) {
160    theme.set(
161        "button_layout",
162        ButtonLayoutThemePreference {
163            padding: Preference::Specific(Gaps::new(6., 12., 6., 12.)),
164            margin: Preference::Specific(Gaps::new_all(0.)),
165            corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
166            width: Preference::Specific(Size::Inner),
167            height: Preference::Specific(Size::Inner),
168        },
169    );
170    theme.set(
171        "compact_button_layout",
172        ButtonLayoutThemePreference {
173            padding: Preference::Specific(Gaps::new(3., 6., 3., 6.)),
174            margin: Preference::Specific(Gaps::new_all(0.)),
175            corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
176            width: Preference::Specific(Size::Inner),
177            height: Preference::Specific(Size::Inner),
178        },
179    );
180    theme.set(
181        "expanded_button_layout",
182        ButtonLayoutThemePreference {
183            padding: Preference::Specific(Gaps::new(10., 16., 10., 16.)),
184            margin: Preference::Specific(Gaps::new_all(0.)),
185            corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
186            width: Preference::Specific(Size::Inner),
187            height: Preference::Specific(Size::Inner),
188        },
189    );
190    theme.set(
191        "button",
192        ButtonColorsThemePreference {
193            background: Preference::Reference("surface_tertiary"),
194            hover_background: Preference::Reference("surface_secondary"),
195            border_fill: Preference::Reference("border"),
196            focus_border_fill: Preference::Reference("border_focus"),
197            color: Preference::Reference("text_primary"),
198        },
199    );
200    theme.set(
201        "filled_button",
202        ButtonColorsThemePreference {
203            background: Preference::Reference("primary"),
204            hover_background: Preference::Reference("tertiary"),
205            border_fill: Preference::Specific(Color::TRANSPARENT),
206            focus_border_fill: Preference::Reference("secondary"),
207            color: Preference::Reference("text_inverse"),
208        },
209    );
210    theme.set(
211        "outline_button",
212        ButtonColorsThemePreference {
213            background: Preference::Reference("surface_tertiary"),
214            hover_background: Preference::Reference("surface_secondary"),
215            border_fill: Preference::Reference("border"),
216            focus_border_fill: Preference::Reference("secondary"),
217            color: Preference::Reference("primary"),
218        },
219    );
220    theme.set(
221        "flat_button",
222        ButtonColorsThemePreference {
223            background: Preference::Specific(Color::TRANSPARENT),
224            hover_background: Preference::Reference("surface_tertiary"),
225            border_fill: Preference::Specific(Color::TRANSPARENT),
226            focus_border_fill: Preference::Reference("border"),
227            color: Preference::Reference("text_primary"),
228        },
229    );
230    theme.set(
231        "card_layout",
232        CardLayoutThemePreference {
233            padding: Preference::Specific(Gaps::new(16., 16., 16., 16.)),
234            corner_radius: Preference::Specific(CornerRadius::new_all(8.)),
235        },
236    );
237    theme.set(
238        "compact_card_layout",
239        CardLayoutThemePreference {
240            padding: Preference::Specific(Gaps::new(8., 12., 8., 12.)),
241            corner_radius: Preference::Specific(CornerRadius::new_all(8.)),
242        },
243    );
244    theme.set(
245        "filled_card",
246        CardColorsThemePreference {
247            background: Preference::Reference("primary"),
248            hover_background: Preference::Reference("tertiary"),
249            border_fill: Preference::Specific(Color::TRANSPARENT),
250            color: Preference::Reference("text_inverse"),
251            shadow: Preference::Reference("shadow"),
252        },
253    );
254    theme.set(
255        "outline_card",
256        CardColorsThemePreference {
257            background: Preference::Reference("surface_tertiary"),
258            hover_background: Preference::Reference("surface_secondary"),
259            border_fill: Preference::Reference("border"),
260            color: Preference::Reference("text_primary"),
261            shadow: Preference::Reference("shadow"),
262        },
263    );
264    theme.set(
265        "accordion",
266        AccordionThemePreference {
267            color: Preference::Reference("text_primary"),
268            background: Preference::Reference("surface_tertiary"),
269            border_fill: Preference::Reference("border"),
270        },
271    );
272    theme.set(
273        "switch",
274        SwitchColorsThemePreference {
275            background: Preference::Reference("surface_secondary"),
276            thumb_background: Preference::Reference("surface_inverse"),
277            toggled_background: Preference::Reference("secondary"),
278            toggled_thumb_background: Preference::Reference("primary"),
279            focus_border_fill: Preference::Reference("border_focus"),
280        },
281    );
282    theme.set(
283        "switch_layout",
284        SwitchLayoutThemePreference {
285            margin: Preference::Specific(Gaps::new_all(0.)),
286            width: Preference::Specific(48.),
287            height: Preference::Specific(28.),
288            padding: Preference::Specific(4.),
289            thumb_size: Preference::Specific(16.),
290            toggled_thumb_size: Preference::Specific(20.),
291            pressed_thumb_size_offset: Preference::Specific(4.),
292            thumb_offset: Preference::Specific(2.),
293            toggled_thumb_offset: Preference::Specific(20.),
294        },
295    );
296    theme.set(
297        "expanded_switch_layout",
298        SwitchLayoutThemePreference {
299            margin: Preference::Specific(Gaps::new_all(0.)),
300            width: Preference::Specific(56.),
301            height: Preference::Specific(32.),
302            padding: Preference::Specific(4.),
303            thumb_size: Preference::Specific(18.),
304            toggled_thumb_size: Preference::Specific(22.),
305            pressed_thumb_size_offset: Preference::Specific(4.),
306            thumb_offset: Preference::Specific(2.),
307            toggled_thumb_offset: Preference::Specific(26.),
308        },
309    );
310    theme.set(
311        "scrollbar",
312        ScrollBarThemePreference {
313            background: Preference::Reference("surface_primary"),
314            thumb_background: Preference::Reference("surface_inverse"),
315            hover_thumb_background: Preference::Reference("surface_inverse_secondary"),
316            active_thumb_background: Preference::Reference("surface_inverse_tertiary"),
317            size: Preference::Specific(15.),
318        },
319    );
320    theme.set(
321        "progressbar",
322        ProgressBarThemePreference {
323            color: Preference::Reference("text_inverse"),
324            background: Preference::Reference("surface_primary"),
325            progress_background: Preference::Reference("primary"),
326            height: Preference::Specific(20.),
327        },
328    );
329    theme.set(
330        "sidebar_item",
331        SideBarItemThemePreference {
332            color: Preference::Reference("text_primary"),
333            background: Preference::Reference("surface_tertiary"),
334            active_background: Preference::Reference("surface_secondary"),
335            hover_background: Preference::Reference("surface_secondary"),
336            focus_border_fill: Preference::Reference("border_focus"),
337            corner_radius: Preference::Specific(CornerRadius::new_all(12.)),
338            margin: Preference::Specific(Gaps::new_all(0.)),
339            padding: Preference::Specific(Gaps::new(8., 12., 8., 12.)),
340        },
341    );
342    #[cfg(feature = "router")]
343    theme.set(
344        "link",
345        LinkThemePreference {
346            color: Preference::Reference("text_highlight"),
347        },
348    );
349    theme.set(
350        "tooltip",
351        TooltipThemePreference {
352            background: Preference::Reference("surface_tertiary"),
353            color: Preference::Reference("text_primary"),
354            border_fill: Preference::Reference("surface_primary"),
355            font_size: Preference::Specific(14.),
356        },
357    );
358    theme.set(
359        "circular_loader",
360        CircularLoaderThemePreference {
361            primary_color: Preference::Reference("surface_primary"),
362        },
363    );
364    theme.set(
365        "input_layout",
366        InputLayoutThemePreference {
367            corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
368            inner_margin: Preference::Specific(Gaps::new(8., 8., 8., 8.)),
369        },
370    );
371    theme.set(
372        "compact_input_layout",
373        InputLayoutThemePreference {
374            corner_radius: Preference::Specific(CornerRadius::new_all(4.)),
375            inner_margin: Preference::Specific(Gaps::new(4., 6., 4., 6.)),
376        },
377    );
378    theme.set(
379        "expanded_input_layout",
380        InputLayoutThemePreference {
381            corner_radius: Preference::Specific(CornerRadius::new_all(8.)),
382            inner_margin: Preference::Specific(Gaps::new(12., 12., 12., 12.)),
383        },
384    );
385    theme.set(
386        "input",
387        InputColorsThemePreference {
388            background: Preference::Reference("surface_tertiary"),
389            focus_background: Preference::Reference("background"),
390            color: Preference::Reference("text_primary"),
391            placeholder_color: Preference::Reference("text_secondary"),
392            border_fill: Preference::Reference("border"),
393            focus_border_fill: Preference::Reference("border_focus"),
394        },
395    );
396    theme.set(
397        "filled_input",
398        InputColorsThemePreference {
399            background: Preference::Reference("primary"),
400            focus_background: Preference::Reference("tertiary"),
401            color: Preference::Reference("text_inverse"),
402            placeholder_color: Preference::Reference("text_inverse"),
403            border_fill: Preference::Specific(Color::TRANSPARENT),
404            focus_border_fill: Preference::Reference("secondary"),
405        },
406    );
407    theme.set(
408        "flat_input",
409        InputColorsThemePreference {
410            background: Preference::Specific(Color::TRANSPARENT),
411            focus_background: Preference::Reference("surface_tertiary"),
412            color: Preference::Reference("text_primary"),
413            placeholder_color: Preference::Reference("text_secondary"),
414            border_fill: Preference::Specific(Color::TRANSPARENT),
415            focus_border_fill: Preference::Reference("border"),
416        },
417    );
418    theme.set(
419        "radio",
420        RadioItemThemePreference {
421            unselected_fill: Preference::Reference("surface_inverse_tertiary"),
422            selected_fill: Preference::Reference("primary"),
423            border_fill: Preference::Reference("surface_primary"),
424        },
425    );
426    theme.set(
427        "checkbox",
428        CheckboxThemePreference {
429            unselected_fill: Preference::Reference("surface_inverse_tertiary"),
430            selected_fill: Preference::Reference("primary"),
431            selected_icon_fill: Preference::Reference("secondary"),
432            border_fill: Preference::Reference("surface_primary"),
433        },
434    );
435    theme.set(
436        "resizable_handle",
437        ResizableHandleThemePreference {
438            background: Preference::Reference("surface_secondary"),
439            hover_background: Preference::Reference("surface_primary"),
440            corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
441        },
442    );
443    theme.set(
444        "floating_tab",
445        FloatingTabThemePreference {
446            background: Preference::Specific(Color::TRANSPARENT),
447            hover_background: Preference::Reference("surface_secondary"),
448            color: Preference::Reference("text_primary"),
449            padding: Preference::Specific(Gaps::new(6., 12., 6., 12.)),
450            width: Preference::Specific(Size::Inner),
451            height: Preference::Specific(Size::Inner),
452            corner_radius: Preference::Specific(CornerRadius::new_all(99.)),
453        },
454    );
455    theme.set(
456        "slider",
457        SliderThemePreference {
458            background: Preference::Reference("surface_primary"),
459            thumb_background: Preference::Reference("secondary"),
460            thumb_inner_background: Preference::Reference("primary"),
461            border_fill: Preference::Reference("surface_primary"),
462        },
463    );
464    theme.set(
465        "color_picker",
466        ColorPickerThemePreference {
467            background: Preference::Reference("surface_tertiary"),
468            border_fill: Preference::Reference("border"),
469            color: Preference::Reference("text_primary"),
470        },
471    );
472    theme.set(
473        "select",
474        SelectThemePreference {
475            width: Preference::Specific(Size::Inner),
476            margin: Preference::Specific(Gaps::new_all(0.)),
477            select_background: Preference::Reference("background"),
478            background_button: Preference::Reference("surface_tertiary"),
479            hover_background: Preference::Reference("surface_secondary"),
480            color: Preference::Reference("text_primary"),
481            border_fill: Preference::Reference("border"),
482            focus_border_fill: Preference::Reference("border_focus"),
483            arrow_fill: Preference::Reference("text_primary"),
484        },
485    );
486    theme.set(
487        "popup",
488        PopupThemePreference {
489            background: Preference::Reference("background"),
490            color: Preference::Reference("text_primary"),
491            width: Preference::Specific(Size::px(500.)),
492            height: Preference::Specific(Size::auto()),
493            padding: Preference::Specific(Gaps::new_all(8.)),
494            spacing: Preference::Specific(4.),
495        },
496    );
497    theme.set(
498        "table",
499        TableThemePreference {
500            background: Preference::Reference("background"),
501            arrow_fill: Preference::Reference("text_primary"),
502            row_background: Preference::Specific(Color::TRANSPARENT),
503            hover_row_background: Preference::Reference("surface_secondary"),
504            divider_fill: Preference::Reference("surface_primary"),
505            corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
506            color: Preference::Reference("text_primary"),
507        },
508    );
509    #[cfg(feature = "markdown")]
510    theme.set(
511        "markdown_viewer",
512        MarkdownViewerThemePreference {
513            color: Preference::Reference("text_primary"),
514            background_code: Preference::Reference("surface_tertiary"),
515            color_code: Preference::Reference("text_primary"),
516            background_blockquote: Preference::Reference("surface_tertiary"),
517            border_blockquote: Preference::Reference("surface_primary"),
518            background_divider: Preference::Reference("border"),
519            heading_h1: Preference::Specific(32.0),
520            heading_h2: Preference::Specific(28.0),
521            heading_h3: Preference::Specific(24.0),
522            heading_h4: Preference::Specific(20.0),
523            heading_h5: Preference::Specific(18.0),
524            heading_h6: Preference::Specific(16.0),
525            paragraph_size: Preference::Specific(16.0),
526            code_font_size: Preference::Specific(14.0),
527            table_font_size: Preference::Specific(14.0),
528        },
529    );
530    theme.set(
531        "chip",
532        ChipThemePreference {
533            background: Preference::Reference("background"),
534            hover_background: Preference::Reference("tertiary"),
535            selected_background: Preference::Reference("primary"),
536            border_fill: Preference::Reference("border"),
537            hover_border_fill: Preference::Reference("tertiary"),
538            selected_border_fill: Preference::Reference("primary"),
539            focus_border_fill: Preference::Reference("secondary"),
540            padding: Preference::Specific(Gaps::new(8., 14., 8., 14.)),
541            margin: Preference::Specific(0.),
542            corner_radius: Preference::Specific(CornerRadius::new_all(99.)),
543            width: Preference::Specific(Size::Inner),
544            height: Preference::Specific(Size::Inner),
545            color: Preference::Reference("text_primary"),
546            hover_color: Preference::Reference("text_inverse"),
547            selected_color: Preference::Reference("text_inverse"),
548            selected_icon_fill: Preference::Reference("secondary"),
549            hover_icon_fill: Preference::Reference("secondary"),
550        },
551    );
552    theme.set(
553        "menu_item",
554        MenuItemThemePreference {
555            background: Preference::Specific(Color::TRANSPARENT),
556            hover_background: Preference::Reference("surface_secondary"),
557            select_background: Preference::Reference("surface_secondary"),
558            border_fill: Preference::Specific(Color::TRANSPARENT),
559            select_border_fill: Preference::Reference("border_focus"),
560            corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
561            color: Preference::Reference("text_primary"),
562        },
563    );
564    theme.set(
565        "menu_container",
566        MenuContainerThemePreference {
567            background: Preference::Reference("background"),
568            padding: Preference::Specific(Gaps::new_all(4.)),
569            shadow: Preference::Reference("shadow"),
570            border_fill: Preference::Reference("surface_primary"),
571            corner_radius: Preference::Specific(CornerRadius::new_all(8.)),
572        },
573    );
574    theme.set(
575        "button_segment",
576        ButtonSegmentThemePreference {
577            background: Preference::Reference("surface_tertiary"),
578            hover_background: Preference::Reference("surface_secondary"),
579            disabled_background: Preference::Reference("disabled"),
580            selected_background: Preference::Reference("surface_secondary"),
581            focus_background: Preference::Reference("surface_secondary"),
582            padding: Preference::Specific(Gaps::new(8., 16., 8., 16.)),
583            selected_padding: Preference::Specific(Gaps::new(8., 12., 8., 12.)),
584            width: Preference::Specific(Size::Inner),
585            height: Preference::Specific(Size::Inner),
586            color: Preference::Reference("text_primary"),
587            selected_icon_fill: Preference::Reference("primary"),
588        },
589    );
590    theme.set(
591        "segmented_button",
592        SegmentedButtonThemePreference {
593            background: Preference::Reference("surface_tertiary"),
594            border_fill: Preference::Reference("border"),
595            corner_radius: Preference::Specific(CornerRadius::new_all(99.)),
596        },
597    );
598    #[cfg(feature = "calendar")]
599    theme.set(
600        "calendar",
601        CalendarThemePreference {
602            background: Preference::Reference("surface_tertiary"),
603            day_background: Preference::Specific(Color::TRANSPARENT),
604            day_hover_background: Preference::Reference("surface_secondary"),
605            day_selected_background: Preference::Reference("surface_primary"),
606            color: Preference::Reference("text_primary"),
607            day_other_month_color: Preference::Reference("text_placeholder"),
608            header_color: Preference::Reference("text_primary"),
609            corner_radius: Preference::Specific(CornerRadius::new_all(8.)),
610            padding: Preference::Specific(Gaps::new_all(12.)),
611            day_corner_radius: Preference::Specific(CornerRadius::new_all(6.)),
612            nav_button_hover_background: Preference::Reference("surface_secondary"),
613        },
614    );
615    #[cfg(feature = "titlebar")]
616    theme.set(
617        "titlebar_button",
618        TitlebarButtonThemePreference {
619            background: Preference::Specific(Color::TRANSPARENT),
620            hover_background: Preference::Reference("surface_secondary"),
621            corner_radius: Preference::Specific(CornerRadius::new_all(0.0)),
622            width: Preference::Specific(Size::Pixels(Length::new(46.0))),
623            height: Preference::Specific(Size::Fill),
624        },
625    );
626    theme.set(
627        "skeleton",
628        SkeletonThemePreference {
629            background: Preference::Reference("surface_primary"),
630            shimmer_color: Preference::Specific(Color::WHITE.with_a(160)),
631            duration: Preference::Specific(Duration::from_millis(1000)),
632            animation: Preference::Specific(SkeletonAnimation::Pulse),
633            corner_radius: Preference::Specific(CornerRadius::new_all(4.)),
634            shimmer_from: Preference::Specific(-320.),
635            shimmer_to: Preference::Specific(960.),
636            shimmer_width: Preference::Specific(300.),
637        },
638    );
639}
640
641/// Light theme with all built-in component themes registered.
642///
643/// The primary color tracks the OS-level [`AccentColor`] when available; the
644/// secondary and tertiary colors are derived from it (lightened / darkened).
645pub fn light_theme() -> Theme {
646    build_theme("light", LIGHT_COLORS)
647}
648
649/// Dark theme with all built-in component themes registered.
650///
651/// The primary color tracks the OS-level [`AccentColor`] when available; the
652/// secondary and tertiary colors are derived from it (lightened / darkened).
653pub fn dark_theme() -> Theme {
654    build_theme("dark", DARK_COLORS)
655}
656
657fn build_theme(name: &'static str, mut colors: ColorsSheet) -> Theme {
658    if let Some(primary) = current_accent_color() {
659        colors.primary = primary;
660        colors.secondary = Color::lerp(primary, Color::WHITE, 0.65);
661        colors.tertiary = Color::lerp(primary, Color::BLACK, 0.23);
662    }
663    let mut theme = Theme::new(name, colors);
664    register_base_component_themes(&mut theme);
665    theme
666}
667
668fn current_accent_color() -> Option<Color> {
669    let platform: Platform = try_consume_root_context()?;
670    let accent = platform.accent_color.read().0?;
671    let [r, g, b, _] = accent.to_u8_array();
672    Some(Color::from_rgb(r, g, b))
673}