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    }
366}
367
368define_theme! {
369    %[component]
370    pub Slider {
371        %[fields]
372        background: Color,
373        thumb_background: Color,
374        thumb_inner_background: Color,
375        border_fill: Color,
376    }
377}
378
379define_theme! {
380    %[component]
381    pub ColorPicker {
382        %[fields]
383        background: Color,
384        color: Color,
385        border_fill: Color,
386    }
387}
388
389define_theme! {
390    %[component]
391    pub Select {
392        %[fields]
393        width: Size,
394        margin: Gaps,
395        select_background: Color,
396        background_button: Color,
397        hover_background: Color,
398        border_fill: Color,
399        focus_border_fill: Color,
400        arrow_fill: Color,
401        color: Color,
402    }
403}
404
405define_theme! {
406    %[component]
407    pub Popup {
408        %[fields]
409        background: Color,
410        color: Color,
411    }
412}
413
414define_theme! {
415    %[component]
416    pub Table {
417        %[fields]
418        background: Color,
419        arrow_fill: Color,
420        hover_row_background: Color,
421        row_background: Color,
422        divider_fill: Color,
423        corner_radius: CornerRadius,
424        color: Color,
425    }
426}
427
428#[cfg(feature = "markdown")]
429define_theme! {
430    %[component]
431    pub MarkdownViewer {
432        %[fields]
433        color: Color,
434        background_code: Color,
435        color_code: Color,
436        background_blockquote: Color,
437        border_blockquote: Color,
438        background_divider: Color,
439        heading_h1: f32,
440        heading_h2: f32,
441        heading_h3: f32,
442        heading_h4: f32,
443        heading_h5: f32,
444        heading_h6: f32,
445        paragraph_size: f32,
446        code_font_size: f32,
447        table_font_size: f32,
448    }
449}
450
451define_theme! {
452    %[component]
453    pub Chip {
454        %[fields]
455        background: Color,
456        hover_background: Color,
457        selected_background: Color,
458        border_fill: Color,
459        selected_border_fill: Color,
460        hover_border_fill: Color,
461        focus_border_fill: Color,
462        margin: f32,
463        corner_radius: CornerRadius,
464        width: Size,
465        height: Size,
466        padding: Gaps,
467        color: Color,
468        hover_color: Color,
469        selected_color: Color,
470        selected_icon_fill: Color,
471        hover_icon_fill: Color,
472    }
473}
474
475define_theme! {
476    %[component]
477    pub MenuContainer {
478        %[fields]
479        background: Color,
480        padding: Gaps,
481        shadow: Color,
482        border_fill: Color,
483        corner_radius: CornerRadius,
484    }
485}
486
487define_theme! {
488    %[component]
489    pub MenuItem {
490       %[fields]
491        background: Color,
492        hover_background: Color,
493        select_background: Color,
494        border_fill: Color,
495        select_border_fill: Color,
496        corner_radius: CornerRadius,
497        color: Color,
498    }
499}
500
501define_theme! {
502    %[component]
503    pub ButtonSegment {
504        %[fields]
505        background: Color,
506        hover_background: Color,
507        disabled_background: Color,
508        selected_background: Color,
509        focus_background: Color,
510        padding: Gaps,
511        selected_padding: Gaps,
512        width: Size,
513        height: Size,
514        color: Color,
515        selected_icon_fill: Color,
516    }
517}
518
519define_theme! {
520    %[component]
521    pub SegmentedButton {
522        %[fields]
523        background: Color,
524        border_fill: Color,
525        corner_radius: CornerRadius,
526    }
527}
528
529#[cfg(feature = "calendar")]
530define_theme! {
531    %[component]
532    pub Calendar {
533        %[fields]
534        background: Color,
535        day_background: Color,
536        day_hover_background: Color,
537        day_selected_background: Color,
538        color: Color,
539        day_other_month_color: Color,
540        header_color: Color,
541        corner_radius: CornerRadius,
542        padding: Gaps,
543        day_corner_radius: CornerRadius,
544        nav_button_hover_background: Color,
545    }
546}
547
548#[cfg(feature = "titlebar")]
549define_theme! {
550    %[component]
551    pub TitlebarButton {
552        %[fields]
553        background: Color,
554        hover_background: Color,
555        corner_radius: CornerRadius,
556        width: Size,
557        height: Size,
558    }
559}