mottes_floem_components/
classes.rs1use floem::{
17 peniko::Color,
18 style::{CursorStyle, Style, StyleValue},
19 style_class,
20 views::{PlaceholderTextClass, RadioButtonClass, RadioButtonDotClass},
21};
22
23use crate::{theme::Theme, BORDER_RADIUS};
24
25style_class!(pub Button);
26style_class!(pub Label);
27style_class!(pub TextInput);
28style_class!(pub ToggleButton);
29style_class!(pub RadioButton);
30style_class!(pub BadgeOne);
31style_class!(pub BadgeTwo);
32style_class!(pub BadgeThree);
33style_class!(pub BadgeFour);
34style_class!(pub BadgeFive);
35
36fn parse_color(color: &str) -> Color {
37 #[allow(clippy::expect_fun_call)]
38 Color::parse(color).expect(format!("failed to parse {color}").as_str())
39}
40
41pub fn construct_theme(theme: Theme) -> Style {
43 Style::new()
44 .class(Button, button(theme))
45 .class(Label, label(theme))
46 .class(TextInput, text_input(theme))
47 .class(ToggleButton, toggle_button(theme))
48 .class(RadioButton, radio_button(theme))
49 .class(
50 BadgeOne,
51 badge(parse_color(theme.base00), parse_color(theme.base0a)),
52 )
53 .class(
54 BadgeTwo,
55 badge(parse_color(theme.base00), parse_color(theme.base0b)),
56 )
57 .class(
58 BadgeThree,
59 badge(parse_color(theme.base00), parse_color(theme.base0c)),
60 )
61 .class(
62 BadgeFour,
63 badge(parse_color(theme.base00), parse_color(theme.base0d)),
64 )
65 .class(BadgeFive, |s| {
66 let badge_style =
67 badge(parse_color(theme.base03), parse_color(theme.base00))(s.clone());
68 s.apply(badge_style)
69 .border(0.5)
70 .border_color(parse_color(theme.base03))
71 })
72}
73
74fn button(theme: Theme) -> impl FnOnce(Style) -> Style {
75 |s| {
76 s.border_radius(BORDER_RADIUS)
77 .border(1.0)
78 .border_color(parse_color(theme.base03))
79 .background(parse_color(theme.base00))
80 .color(parse_color(theme.base05))
81 .hover(|s| {
82 s.background(parse_color(theme.base01))
83 .color(parse_color(theme.base05))
84 })
85 .active(|s| {
86 s.background(parse_color(theme.base0a))
87 .color(parse_color(theme.base00))
88 })
89 .focus(|s| {
90 s.background(parse_color(theme.base01))
91 .color(parse_color(theme.base05))
92 .hover(|s| s.background(parse_color(theme.base00)))
93 .border_color(parse_color(theme.base03))
94 })
95 .disabled(|s| s.background(parse_color(theme.base01).multiply_alpha(0.6)))
96 }
97}
98
99fn label(theme: Theme) -> impl FnOnce(Style) -> Style {
100 |s| s.color(parse_color(theme.base05))
101}
102
103fn text_input(theme: Theme) -> impl FnOnce(Style) -> Style {
104 |s| {
105 s.color(parse_color(theme.base05))
106 .border_radius(BORDER_RADIUS)
107 .border_color(parse_color(theme.base03))
108 .background(parse_color(theme.base00))
109 .hover(|s| s.background(parse_color(theme.base00)))
110 .focus(|s| {
111 s.hover(|s| s.background(parse_color(theme.base00)))
112 .border_color(parse_color(theme.base0a))
113 })
114 .cursor_color(StyleValue::Val(parse_color(theme.base05).into()))
115 .cursor(CursorStyle::Text)
116 .disabled(|s| {
117 s.color(parse_color(theme.base05).multiply_alpha(0.6))
118 .background(parse_color(theme.base03).multiply_alpha(0.6))
119 })
120 .class(PlaceholderTextClass, |s| s.color(parse_color(theme.base03)))
121 }
122}
123
124fn toggle_button(theme: Theme) -> impl FnOnce(Style) -> Style {
125 |s| {
126 {
127 s.border_radius(BORDER_RADIUS)
128 .background(parse_color(theme.base00))
129 .color(parse_color(theme.base05))
130 .border_color(parse_color(theme.base03))
131 .hover(|s| s.background(parse_color(theme.base00)))
132 .focus(|s| {
133 s.hover(|s| s.background(parse_color(theme.base00)))
134 .border_color(parse_color(theme.base0a))
135 })
136 .disabled(|s| {
137 s.color(parse_color(theme.base05).multiply_alpha(0.6))
138 .background(parse_color(theme.base03).multiply_alpha(0.6))
139 })
140 .active(|s| s.background(parse_color(theme.base02)))
141 }
143 }
144}
145
146fn radio_button(theme: Theme) -> impl FnOnce(Style) -> Style {
147 |s| {
148 s.class(RadioButtonClass, |s| {
149 s.background(parse_color(theme.base00))
150 .border_color(parse_color(theme.base03))
151 .hover(|s| s.background(parse_color(theme.base00)))
152 .focus(|s| {
153 s.hover(|s| s.background(parse_color(theme.base00)))
154 .border_color(parse_color(theme.base0a))
155 })
156 .disabled(|s| {
157 s.color(parse_color(theme.base05).multiply_alpha(0.6))
158 .background(parse_color(theme.base03).multiply_alpha(0.6))
159 })
160 .active(|s| s.background(parse_color(theme.base02)))
161 })
162 .class(RadioButtonDotClass, |s| {
163 s.background(parse_color(theme.base0a))
164 })
165 }
166}
167
168fn badge(text_color: Color, badge_color: Color) -> impl FnOnce(Style) -> Style {
169 move |s| {
170 s.border_radius(BORDER_RADIUS)
171 .color(text_color)
172 .background(badge_color)
173 .height(17)
174 .width(75)
175 .padding_top(2)
176 .padding_left(5)
177 }
178}