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