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