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