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        font_size: f32,
285    }
286}
287
288define_theme! {
289    %[component]
290    pub CircularLoader {
291        %[fields]
292        primary_color: Color,
293        inversed_color: Color,
294    }
295}
296
297define_theme! {
298    for = Input;
299    theme_field = theme_layout;
300
301    %[component]
302    pub InputLayout {
303        %[fields]
304        corner_radius: CornerRadius,
305        inner_margin: Gaps,
306    }
307}
308
309define_theme! {
310    for = Input;
311    theme_field = theme_colors;
312
313    %[component]
314    pub InputColors {
315        %[fields]
316        background: Color,
317        hover_background: Color,
318        border_fill: Color,
319        focus_border_fill: Color,
320        color: Color,
321        placeholder_color: Color,
322    }
323}
324
325define_theme! {
326    %[component]
327    pub RadioItem {
328        %[fields]
329        unselected_fill: Color,
330        selected_fill: Color,
331        border_fill: Color,
332    }
333}
334
335define_theme! {
336    %[component]
337    pub Checkbox {
338        %[fields]
339        unselected_fill: Color,
340        selected_fill: Color,
341        selected_icon_fill: Color,
342        border_fill: Color,
343    }
344}
345
346define_theme! {
347    %[component]
348    pub ResizableHandle {
349        %[fields]
350        background: Color,
351        hover_background: Color,
352        corner_radius: CornerRadius,
353    }
354}
355
356define_theme! {
357    %[component]
358    pub FloatingTab {
359        %[fields]
360        background: Color,
361        hover_background: Color,
362        width: Size,
363        height: Size,
364        padding: Gaps,
365        color: Color,
366        corner_radius: CornerRadius,
367    }
368}
369
370define_theme! {
371    %[component]
372    pub Slider {
373        %[fields]
374        background: Color,
375        thumb_background: Color,
376        thumb_inner_background: Color,
377        border_fill: Color,
378    }
379}
380
381define_theme! {
382    %[component]
383    pub ColorPicker {
384        %[fields]
385        background: Color,
386        color: Color,
387        border_fill: Color,
388    }
389}
390
391define_theme! {
392    %[component]
393    pub Select {
394        %[fields]
395        width: Size,
396        margin: Gaps,
397        select_background: Color,
398        background_button: Color,
399        hover_background: Color,
400        border_fill: Color,
401        focus_border_fill: Color,
402        arrow_fill: Color,
403        color: Color,
404    }
405}
406
407define_theme! {
408    %[component]
409    pub Popup {
410        %[fields]
411        background: Color,
412        color: Color,
413    }
414}
415
416define_theme! {
417    %[component]
418    pub Table {
419        %[fields]
420        background: Color,
421        arrow_fill: Color,
422        hover_row_background: Color,
423        row_background: Color,
424        divider_fill: Color,
425        corner_radius: CornerRadius,
426        color: Color,
427    }
428}
429
430#[cfg(feature = "markdown")]
431define_theme! {
432    %[component]
433    pub MarkdownViewer {
434        %[fields]
435        color: Color,
436        background_code: Color,
437        color_code: Color,
438        background_blockquote: Color,
439        border_blockquote: Color,
440        background_divider: Color,
441        heading_h1: f32,
442        heading_h2: f32,
443        heading_h3: f32,
444        heading_h4: f32,
445        heading_h5: f32,
446        heading_h6: f32,
447        paragraph_size: f32,
448        code_font_size: f32,
449        table_font_size: f32,
450    }
451}
452
453define_theme! {
454    %[component]
455    pub Chip {
456        %[fields]
457        background: Color,
458        hover_background: Color,
459        selected_background: Color,
460        border_fill: Color,
461        selected_border_fill: Color,
462        hover_border_fill: Color,
463        focus_border_fill: Color,
464        margin: f32,
465        corner_radius: CornerRadius,
466        width: Size,
467        height: Size,
468        padding: Gaps,
469        color: Color,
470        hover_color: Color,
471        selected_color: Color,
472        selected_icon_fill: Color,
473        hover_icon_fill: Color,
474    }
475}
476
477define_theme! {
478    %[component]
479    pub MenuContainer {
480        %[fields]
481        background: Color,
482        padding: Gaps,
483        shadow: Color,
484        border_fill: Color,
485        corner_radius: CornerRadius,
486    }
487}
488
489define_theme! {
490    %[component]
491    pub MenuItem {
492       %[fields]
493        background: Color,
494        hover_background: Color,
495        select_background: Color,
496        border_fill: Color,
497        select_border_fill: Color,
498        corner_radius: CornerRadius,
499        color: Color,
500    }
501}
502
503define_theme! {
504    %[component]
505    pub ButtonSegment {
506        %[fields]
507        background: Color,
508        hover_background: Color,
509        disabled_background: Color,
510        selected_background: Color,
511        focus_background: Color,
512        padding: Gaps,
513        selected_padding: Gaps,
514        width: Size,
515        height: Size,
516        color: Color,
517        selected_icon_fill: Color,
518    }
519}
520
521define_theme! {
522    %[component]
523    pub SegmentedButton {
524        %[fields]
525        background: Color,
526        border_fill: Color,
527        corner_radius: CornerRadius,
528    }
529}
530
531#[cfg(feature = "calendar")]
532define_theme! {
533    %[component]
534    pub Calendar {
535        %[fields]
536        background: Color,
537        day_background: Color,
538        day_hover_background: Color,
539        day_selected_background: Color,
540        color: Color,
541        day_other_month_color: Color,
542        header_color: Color,
543        corner_radius: CornerRadius,
544        padding: Gaps,
545        day_corner_radius: CornerRadius,
546        nav_button_hover_background: Color,
547    }
548}
549
550#[cfg(feature = "titlebar")]
551define_theme! {
552    %[component]
553    pub TitlebarButton {
554        %[fields]
555        background: Color,
556        hover_background: Color,
557        corner_radius: CornerRadius,
558        width: Size,
559        height: Size,
560    }
561}