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