Skip to main content

freya_components/theming/
component_themes.rs

1use freya_core::prelude::*;
2use torin::{
3    gaps::Gaps,
4    size::Size,
5};
6
7#[cfg(feature = "calendar")]
8use crate::calendar::Calendar;
9#[cfg(feature = "router")]
10use crate::link::Link;
11#[cfg(feature = "markdown")]
12use crate::markdown::MarkdownViewer;
13#[cfg(feature = "titlebar")]
14use crate::titlebar::TitlebarButton;
15use crate::{
16    accordion::Accordion,
17    button::Button,
18    card::Card,
19    checkbox::Checkbox,
20    chip::Chip,
21    color_picker::ColorPicker,
22    define_theme,
23    floating_tab::FloatingTab,
24    input::Input,
25    loader::CircularLoader,
26    menu::{
27        MenuContainer,
28        MenuItem,
29    },
30    popup::Popup,
31    progressbar::ProgressBar,
32    radio_item::RadioItem,
33    resizable_container::ResizableHandle,
34    scrollviews::ScrollBar,
35    segmented_button::{
36        ButtonSegment,
37        SegmentedButton,
38    },
39    select::Select,
40    sidebar::SideBarItem,
41    slider::Slider,
42    switch::Switch,
43    table::Table,
44    theming::themes::LIGHT_THEME,
45    tooltip::Tooltip,
46};
47
48#[derive(Clone, Debug, PartialEq)]
49pub struct Theme {
50    pub name: &'static str,
51    pub colors: ColorsSheet,
52    pub button_layout: ButtonLayoutThemePreference,
53    pub compact_button_layout: ButtonLayoutThemePreference,
54    pub expanded_button_layout: ButtonLayoutThemePreference,
55    pub button: ButtonColorsThemePreference,
56    pub filled_button: ButtonColorsThemePreference,
57    pub outline_button: ButtonColorsThemePreference,
58    pub flat_button: ButtonColorsThemePreference,
59    pub card_layout: CardLayoutThemePreference,
60    pub compact_card_layout: CardLayoutThemePreference,
61    pub filled_card: CardColorsThemePreference,
62    pub outline_card: CardColorsThemePreference,
63    pub accordion: AccordionThemePreference,
64    pub switch: SwitchThemePreference,
65    pub scrollbar: ScrollBarThemePreference,
66    pub progressbar: ProgressBarThemePreference,
67    pub sidebar_item: SideBarItemThemePreference,
68    #[cfg(feature = "router")]
69    pub link: LinkThemePreference,
70    pub tooltip: TooltipThemePreference,
71    pub circular_loader: CircularLoaderThemePreference,
72    pub input_layout: InputLayoutThemePreference,
73    pub compact_input_layout: InputLayoutThemePreference,
74    pub expanded_input_layout: InputLayoutThemePreference,
75    pub input: InputColorsThemePreference,
76    pub filled_input: InputColorsThemePreference,
77    pub flat_input: InputColorsThemePreference,
78    pub radio: RadioItemThemePreference,
79    pub checkbox: CheckboxThemePreference,
80    pub resizable_handle: ResizableHandleThemePreference,
81    pub floating_tab: FloatingTabThemePreference,
82    pub slider: SliderThemePreference,
83    pub color_picker: ColorPickerThemePreference,
84    pub select: SelectThemePreference,
85    pub popup: PopupThemePreference,
86    pub table: TableThemePreference,
87    #[cfg(feature = "markdown")]
88    pub markdown_viewer: MarkdownViewerThemePreference,
89    pub chip: ChipThemePreference,
90    pub menu_item: MenuItemThemePreference,
91    pub menu_container: MenuContainerThemePreference,
92    pub button_segment: ButtonSegmentThemePreference,
93    pub segmented_button: SegmentedButtonThemePreference,
94    #[cfg(feature = "calendar")]
95    pub calendar: CalendarThemePreference,
96    #[cfg(feature = "titlebar")]
97    pub titlebar_button: TitlebarButtonThemePreference,
98}
99
100impl Default for Theme {
101    fn default() -> Self {
102        LIGHT_THEME
103    }
104}
105
106#[derive(Clone, Debug, PartialEq, Eq)]
107pub struct ColorsSheet {
108    // Brand & Accent
109    pub primary: Color,
110    pub secondary: Color,
111    pub tertiary: Color,
112
113    // Status / Semantic colors
114    pub success: Color,
115    pub warning: Color,
116    pub error: Color,
117    pub info: Color,
118
119    // Surfaces / Backgrounds
120    pub background: Color,
121    pub surface_primary: Color,
122    pub surface_secondary: Color,
123    pub surface_tertiary: Color,
124    pub surface_inverse: Color,
125    pub surface_inverse_secondary: Color,
126    pub surface_inverse_tertiary: Color,
127
128    // Borders
129    pub border: Color,
130    pub border_focus: Color,
131    pub border_disabled: Color,
132
133    // Text / Content
134    pub text_primary: Color,
135    pub text_secondary: Color,
136    pub text_placeholder: Color,
137    pub text_inverse: Color,
138    pub text_highlight: Color,
139
140    // States / Interaction
141    pub hover: Color,
142    pub focus: Color,
143    pub active: Color,
144    pub disabled: Color,
145
146    // Utility
147    pub overlay: Color,
148    pub shadow: Color,
149}
150
151define_theme! {
152    for = Button;
153    theme_field = theme_layout;
154
155    %[component]
156    pub ButtonLayout {
157        %[fields]
158        margin: Gaps,
159        corner_radius: CornerRadius,
160        width: Size,
161        height: Size,
162        padding: Gaps,
163    }
164}
165
166define_theme! {
167    for = Button;
168    theme_field = theme_colors;
169
170    %[component]
171    pub ButtonColors {
172        %[fields]
173        background: Color,
174        hover_background: Color,
175        border_fill: Color,
176        focus_border_fill: Color,
177        color: Color,
178    }
179}
180
181define_theme! {
182    for = Card;
183    theme_field = theme_layout;
184
185    %[component]
186    pub CardLayout {
187        %[fields]
188        corner_radius: CornerRadius,
189        padding: Gaps,
190    }
191}
192
193define_theme! {
194    for = Card;
195    theme_field = theme_colors;
196
197    %[component]
198    pub CardColors {
199        %[fields]
200        background: Color,
201        hover_background: Color,
202        border_fill: Color,
203        color: Color,
204        shadow: Color,
205    }
206}
207
208define_theme! {
209    %[component]
210    pub Accordion {
211        %[fields]
212        color: Color,
213        background: Color,
214        border_fill: Color,
215    }
216}
217
218define_theme! {
219    %[component]
220    pub Switch {
221        %[fields]
222        margin: Gaps,
223        background: Color,
224        thumb_background: Color,
225        toggled_background: Color,
226        toggled_thumb_background: Color,
227        focus_border_fill: Color,
228    }
229}
230
231define_theme! {
232    %[component]
233    pub ScrollBar {
234        %[fields]
235        background: Color,
236        thumb_background: Color,
237        hover_thumb_background: Color,
238        active_thumb_background: Color,
239        size: f32,
240    }
241}
242
243define_theme! {
244    %[component]
245    pub ProgressBar {
246        %[fields]
247        color: Color,
248        background: Color,
249        progress_background: Color,
250        height: f32,
251    }
252}
253
254define_theme! {
255    %[component]
256    pub SideBarItem {
257        %[fields]
258        color: Color,
259        background: Color,
260        hover_background: Color,
261        active_background: Color,
262        corner_radius: CornerRadius,
263        margin: Gaps,
264        padding: Gaps,
265    }
266}
267
268#[cfg(feature = "router")]
269define_theme! {
270    %[component]
271    pub Link {
272        %[fields]
273        color: Color,
274    }
275}
276
277define_theme! {
278    %[component]
279    pub Tooltip {
280        %[fields]
281        color: Color,
282        background: Color,
283        border_fill: Color,
284    }
285}
286
287define_theme! {
288    %[component]
289    pub CircularLoader {
290        %[fields]
291        primary_color: Color,
292        inversed_color: Color,
293    }
294}
295
296define_theme! {
297    for = Input;
298    theme_field = theme_layout;
299
300    %[component]
301    pub InputLayout {
302        %[fields]
303        corner_radius: CornerRadius,
304        inner_margin: Gaps,
305    }
306}
307
308define_theme! {
309    for = Input;
310    theme_field = theme_colors;
311
312    %[component]
313    pub InputColors {
314        %[fields]
315        background: Color,
316        hover_background: Color,
317        border_fill: Color,
318        focus_border_fill: Color,
319        color: Color,
320        placeholder_color: Color,
321    }
322}
323
324define_theme! {
325    %[component]
326    pub RadioItem {
327        %[fields]
328        unselected_fill: Color,
329        selected_fill: Color,
330        border_fill: Color,
331    }
332}
333
334define_theme! {
335    %[component]
336    pub Checkbox {
337        %[fields]
338        unselected_fill: Color,
339        selected_fill: Color,
340        selected_icon_fill: Color,
341        border_fill: Color,
342    }
343}
344
345define_theme! {
346    %[component]
347    pub ResizableHandle {
348        %[fields]
349        background: Color,
350        hover_background: Color,
351        corner_radius: CornerRadius,
352    }
353}
354
355define_theme! {
356    %[component]
357    pub FloatingTab {
358        %[fields]
359        background: Color,
360        hover_background: Color,
361        width: Size,
362        height: Size,
363        padding: Gaps,
364        color: Color,
365        corner_radius: CornerRadius,
366    }
367}
368
369define_theme! {
370    %[component]
371    pub Slider {
372        %[fields]
373        background: Color,
374        thumb_background: Color,
375        thumb_inner_background: Color,
376        border_fill: Color,
377    }
378}
379
380define_theme! {
381    %[component]
382    pub ColorPicker {
383        %[fields]
384        background: Color,
385        color: Color,
386        border_fill: Color,
387    }
388}
389
390define_theme! {
391    %[component]
392    pub Select {
393        %[fields]
394        width: Size,
395        margin: Gaps,
396        select_background: Color,
397        background_button: Color,
398        hover_background: Color,
399        border_fill: Color,
400        focus_border_fill: Color,
401        arrow_fill: Color,
402        color: Color,
403    }
404}
405
406define_theme! {
407    %[component]
408    pub Popup {
409        %[fields]
410        background: Color,
411        color: Color,
412    }
413}
414
415define_theme! {
416    %[component]
417    pub Table {
418        %[fields]
419        background: Color,
420        arrow_fill: Color,
421        hover_row_background: Color,
422        row_background: Color,
423        divider_fill: Color,
424        corner_radius: CornerRadius,
425        color: Color,
426    }
427}
428
429#[cfg(feature = "markdown")]
430define_theme! {
431    %[component]
432    pub MarkdownViewer {
433        %[fields]
434        color: Color,
435        background_code: Color,
436        color_code: Color,
437        background_blockquote: Color,
438        border_blockquote: Color,
439        background_divider: Color,
440        heading_h1: f32,
441        heading_h2: f32,
442        heading_h3: f32,
443        heading_h4: f32,
444        heading_h5: f32,
445        heading_h6: f32,
446        paragraph_size: f32,
447        code_font_size: f32,
448        table_font_size: f32,
449    }
450}
451
452define_theme! {
453    %[component]
454    pub Chip {
455        %[fields]
456        background: Color,
457        hover_background: Color,
458        selected_background: Color,
459        border_fill: Color,
460        selected_border_fill: Color,
461        hover_border_fill: Color,
462        focus_border_fill: Color,
463        margin: f32,
464        corner_radius: CornerRadius,
465        width: Size,
466        height: Size,
467        padding: Gaps,
468        color: Color,
469        hover_color: Color,
470        selected_color: Color,
471        selected_icon_fill: Color,
472        hover_icon_fill: Color,
473    }
474}
475
476define_theme! {
477    %[component]
478    pub MenuContainer {
479        %[fields]
480        background: Color,
481        padding: Gaps,
482        shadow: Color,
483        border_fill: Color,
484        corner_radius: CornerRadius,
485    }
486}
487
488define_theme! {
489    %[component]
490    pub MenuItem {
491       %[fields]
492        background: Color,
493        hover_background: Color,
494        select_background: Color,
495        border_fill: Color,
496        select_border_fill: Color,
497        corner_radius: CornerRadius,
498        color: Color,
499    }
500}
501
502define_theme! {
503    %[component]
504    pub ButtonSegment {
505        %[fields]
506        background: Color,
507        hover_background: Color,
508        disabled_background: Color,
509        selected_background: Color,
510        focus_background: Color,
511        padding: Gaps,
512        selected_padding: Gaps,
513        width: Size,
514        height: Size,
515        color: Color,
516        selected_icon_fill: Color,
517    }
518}
519
520define_theme! {
521    %[component]
522    pub SegmentedButton {
523        %[fields]
524        background: Color,
525        border_fill: Color,
526        corner_radius: CornerRadius,
527    }
528}
529
530#[cfg(feature = "calendar")]
531define_theme! {
532    %[component]
533    pub Calendar {
534        %[fields]
535        background: Color,
536        day_background: Color,
537        day_hover_background: Color,
538        day_selected_background: Color,
539        color: Color,
540        day_other_month_color: Color,
541        header_color: Color,
542        corner_radius: CornerRadius,
543        padding: Gaps,
544        day_corner_radius: CornerRadius,
545        nav_button_hover_background: Color,
546    }
547}
548
549#[cfg(feature = "titlebar")]
550define_theme! {
551    %[component]
552    pub TitlebarButton {
553        %[fields]
554        background: Color,
555        hover_background: Color,
556        corner_radius: CornerRadius,
557        width: Size,
558        height: Size,
559    }
560}