freya_components/theming/
component_themes.rs

1use freya_core::prelude::*;
2use torin::{
3    gaps::Gaps,
4    size::Size,
5};
6
7#[cfg(feature = "router")]
8use crate::link::Link;
9use crate::{
10    accordion::Accordion,
11    button::Button,
12    checkbox::Checkbox,
13    chip::Chip,
14    define_theme,
15    dropdown::{
16        Dropdown,
17        DropdownItem,
18    },
19    floating_tab::FloatingTab,
20    input::Input,
21    loader::CircularLoader,
22    menu::{
23        MenuContainer,
24        MenuItem,
25    },
26    popup::Popup,
27    progressbar::ProgressBar,
28    radio_item::RadioItem,
29    resizable_container::ResizableHandle,
30    scrollviews::ScrollBar,
31    sidebar::{
32        SideBar,
33        SideBarItem,
34    },
35    slider::Slider,
36    switch::Switch,
37    table::Table,
38    theming::themes::LIGHT_THEME,
39    tooltip::Tooltip,
40};
41
42#[derive(Clone, Debug, PartialEq)]
43pub struct Theme {
44    pub name: &'static str,
45    pub colors: ColorsSheet,
46    pub button_layout: ButtonLayoutThemePreference,
47    pub compact_button_layout: ButtonLayoutThemePreference,
48    pub expanded_button_layout: ButtonLayoutThemePreference,
49    pub button: ButtonColorsThemePreference,
50    pub filled_button: ButtonColorsThemePreference,
51    pub outline_button: ButtonColorsThemePreference,
52    pub accordion: AccordionThemePreference,
53    pub switch: SwitchThemePreference,
54    pub scrollbar: ScrollBarThemePreference,
55    pub progressbar: ProgressBarThemePreference,
56    pub sidebar: SideBarThemePreference,
57    pub sidebar_item: SideBarItemThemePreference,
58    #[cfg(feature = "router")]
59    pub link: LinkThemePreference,
60    pub tooltip: TooltipThemePreference,
61    pub circular_loader: CircularLoaderThemePreference,
62    pub input: InputThemePreference,
63    pub radio: RadioItemThemePreference,
64    pub checkbox: CheckboxThemePreference,
65    pub resizable_handle: ResizableHandleThemePreference,
66    pub floating_tab: FloatingTabThemePreference,
67    pub slider: SliderThemePreference,
68    pub dropdown: DropdownThemePreference,
69    pub dropdown_item: DropdownItemThemePreference,
70    pub popup: PopupThemePreference,
71    pub table: TableThemePreference,
72    pub chip: ChipThemePreference,
73    pub menu_item: MenuItemThemePreference,
74    pub menu_container: MenuContainerThemePreference,
75}
76
77impl Default for Theme {
78    fn default() -> Self {
79        LIGHT_THEME
80    }
81}
82
83#[derive(Clone, Debug, PartialEq, Eq)]
84pub struct ColorsSheet {
85    // Brand & Accent
86    pub primary: Color,
87    pub secondary: Color,
88    pub tertiary: Color,
89
90    // Status / Semantic colors
91    pub success: Color,
92    pub warning: Color,
93    pub error: Color,
94    pub info: Color,
95
96    // Surfaces / Backgrounds
97    pub background: Color,
98    pub surface_primary: Color,
99    pub surface_secondary: Color,
100    pub surface_tertiary: Color,
101    pub surface_inverse: Color,
102    pub surface_inverse_secondary: Color,
103    pub surface_inverse_tertiary: Color,
104
105    // Borders
106    pub border: Color,
107    pub border_focus: Color,
108    pub border_disabled: Color,
109
110    // Text / Content
111    pub text_primary: Color,
112    pub text_secondary: Color,
113    pub text_placeholder: Color,
114    pub text_inverse: Color,
115    pub text_highlight: Color,
116
117    // States / Interaction
118    pub hover: Color,
119    pub focus: Color,
120    pub active: Color,
121    pub disabled: Color,
122
123    // Utility
124    pub overlay: Color,
125    pub shadow: Color,
126}
127
128define_theme! {
129    for = Button;
130    theme_field = theme_layout;
131
132    %[component]
133    pub ButtonLayout {
134        %[fields]
135        margin: Gaps,
136        corner_radius: CornerRadius,
137        width: Size,
138        height: Size,
139        padding: Gaps,
140    }
141}
142
143define_theme! {
144    for = Button;
145    theme_field = theme_colors;
146
147    %[component]
148    pub ButtonColors {
149        %[fields]
150        background: Color,
151        hover_background: Color,
152        border_fill: Color,
153        focus_border_fill: Color,
154        color: Color,
155    }
156}
157
158define_theme! {
159    %[component]
160    pub Accordion {
161        %[fields]
162        color: Color,
163        background: Color,
164        border_fill: Color,
165    }
166}
167
168define_theme! {
169    %[component]
170    pub Switch {
171        %[fields]
172        margin: Gaps,
173        background: Color,
174        thumb_background: Color,
175        toggled_background: Color,
176        toggled_thumb_background: Color,
177        focus_border_fill: Color,
178    }
179}
180
181define_theme! {
182    %[component]
183    pub ScrollBar {
184        %[fields]
185        background: Color,
186        thumb_background: Color,
187        hover_thumb_background: Color,
188        active_thumb_background: Color,
189        size: f32,
190    }
191}
192
193define_theme! {
194    %[component]
195    pub ProgressBar {
196        %[fields]
197        color: Color,
198        background: Color,
199        progress_background: Color,
200        height: f32,
201    }
202}
203
204define_theme! {
205    %[component]
206    pub SideBar {
207       %[fields]
208        color: Color,
209        background: Color,
210        padding: Gaps,
211        spacing: f32,
212    }
213}
214
215define_theme! {
216    %[component]
217    pub SideBarItem {
218        %[fields]
219        color: Color,
220        background: Color,
221        hover_background: Color,
222        corner_radius: CornerRadius,
223        margin: Gaps,
224        padding: Gaps,
225    }
226}
227
228#[cfg(feature = "router")]
229define_theme! {
230    %[component]
231    pub Link {
232        %[fields]
233        color: Color,
234    }
235}
236
237define_theme! {
238    %[component]
239    pub Tooltip {
240        %[fields]
241        color: Color,
242        background: Color,
243        border_fill: Color,
244    }
245}
246
247define_theme! {
248    %[component]
249    pub CircularLoader {
250        %[fields]
251        primary_color: Color,
252        inversed_color: Color,
253    }
254}
255
256define_theme! {
257    %[component]
258    pub Input {
259        %[fields]
260        background: Color,
261        hover_background: Color,
262        border_fill: Color,
263        focus_border_fill: Color,
264        corner_radius: CornerRadius,
265        inner_margin: Gaps,
266        color: Color,
267        placeholder_color: Color,
268    }
269}
270
271define_theme! {
272    %[component]
273    pub RadioItem {
274        %[fields]
275        unselected_fill: Color,
276        selected_fill: Color,
277        border_fill: Color,
278    }
279}
280
281define_theme! {
282    %[component]
283    pub Checkbox {
284        %[fields]
285        unselected_fill: Color,
286        selected_fill: Color,
287        selected_icon_fill: Color,
288        border_fill: Color,
289    }
290}
291
292define_theme! {
293    %[component]
294    pub ResizableHandle {
295        %[fields]
296        background: Color,
297        hover_background: Color,
298    }
299}
300
301define_theme! {
302    %[component]
303    pub FloatingTab {
304        %[fields]
305        background: Color,
306        hover_background: Color,
307        width: Size,
308        height: Size,
309        padding: Gaps,
310        color: Color,
311    }
312}
313
314define_theme! {
315    %[component]
316    pub Slider {
317        %[fields]
318        background: Color,
319        thumb_background: Color,
320        thumb_inner_background: Color,
321        border_fill: Color,
322    }
323}
324
325define_theme! {
326    %[component]
327    pub Dropdown {
328        %[fields]
329        width: Size,
330        margin: Gaps,
331        dropdown_background: Color,
332        background_button: Color,
333        hover_background: Color,
334        border_fill: Color,
335        focus_border_fill: Color,
336        arrow_fill: Color,
337        color: Color,
338    }
339}
340
341define_theme! {
342    %[component]
343    pub DropdownItem {
344        %[fields]
345        background: Color,
346        select_background: Color,
347        hover_background: Color,
348        border_fill: Color,
349        select_border_fill: Color,
350        color: Color,
351    }
352}
353
354define_theme! {
355    %[component]
356    pub Popup {
357        %[fields]
358        background: Color,
359        color: Color,
360    }
361}
362
363define_theme! {
364    %[component]
365    pub Table {
366        %[fields]
367        background: Color,
368        arrow_fill: Color,
369        hover_row_background: Color,
370        row_background: Color,
371        divider_fill: Color,
372        corner_radius: CornerRadius,
373        color: Color,
374    }
375}
376
377define_theme! {
378    %[component]
379    pub Chip {
380        %[fields]
381        background: Color,
382        hover_background: Color,
383        selected_background: Color,
384        border_fill: Color,
385        selected_border_fill: Color,
386        hover_border_fill: Color,
387        focus_border_fill: Color,
388        margin: f32,
389        corner_radius: CornerRadius,
390        width: Size,
391        height: Size,
392        padding: Gaps,
393        color: Color,
394        hover_color: Color,
395        selected_color: Color,
396        selected_icon_fill: Color,
397        hover_icon_fill: Color,
398    }
399}
400
401define_theme! {
402    %[component]
403    pub MenuContainer {
404        %[fields]
405        background: Color,
406        padding: Gaps,
407        shadow: Color,
408        border_fill: Color,
409        corner_radius: CornerRadius,
410    }
411}
412
413define_theme! {
414    %[component]
415    pub MenuItem {
416       %[fields]
417        hover_background: Color,
418        corner_radius: CornerRadius,
419        color: Color,
420    }
421}