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