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