teksilo_widgets/styles/
recipe_color_picker_style.rs1use teksilo_core::build_context::BuildContext;
17use teksilo_core::styles::{ColorPickerLayout, ColorPickerStyle, ColorPickerStyleConfig};
18use teksilo_core::widget_id::WidgetId;
19use teksilo_tokens::Color;
20
21use crate::panel::Panel;
22use crate::primitives::{HStack, VStack};
23
24pub const CANVAS_WIDTH: f32 = 224.0;
28pub const CANVAS_HEIGHT: f32 = 192.0;
29pub const CANVAS_CORNER_RADIUS: f32 = 4.0;
30
31pub const STRIP_THICKNESS: f32 = 14.0;
33pub const STRIP_LENGTH: f32 = 192.0;
34pub const STRIP_CORNER_RADIUS: f32 = 4.0;
35
36pub const INDICATOR_RADIUS: f32 = 7.0;
38pub const INDICATOR_OUTER_STROKE_WIDTH: f32 = 1.5;
39pub const INDICATOR_INNER_STROKE_WIDTH: f32 = 1.0;
40pub const INDICATOR_OUTER_COLOR: Color = Color::WHITE;
41pub const INDICATOR_INNER_COLOR: Color = Color::new(0.0, 0.0, 0.0, 0.6);
42
43pub const STRIP_THUMB_WIDTH: f32 = 18.0;
45pub const STRIP_THUMB_HEIGHT: f32 = 8.0;
46pub const STRIP_THUMB_CORNER_RADIUS: f32 = 2.0;
47
48pub const PADDING: f32 = 12.0;
50pub const GAP: f32 = 10.0;
51
52pub const SWATCH_SIZE: f32 = 22.0;
54pub const SWATCH_SPACING: f32 = 6.0;
55pub const SWATCH_CORNER_RADIUS: f32 = 4.0;
56pub const SWATCH_SELECTED_STROKE_WIDTH: f32 = 2.0;
57
58pub const CHECKER_CELL: f32 = 6.0;
61pub const CHECKER_COLOR_A: Color = Color::new(0.78, 0.78, 0.78, 1.0);
62pub const CHECKER_COLOR_B: Color = Color::WHITE;
63
64pub const PREVIEW_WIDTH: f32 = 64.0;
67pub const PREVIEW_HEIGHT: f32 = 28.0;
68pub const PREVIEW_CORNER_RADIUS: f32 = 4.0;
69
70pub const SPINNER_FIELD_WIDTH: f32 = 56.0;
72pub const HEX_FIELD_WIDTH: f32 = 96.0;
73
74#[derive(Debug, Clone, Copy, PartialEq)]
81pub struct ColorPickerRecipe {
82 pub canvas_width: f32,
84 pub canvas_height: f32,
85 pub canvas_corner_radius: f32,
86 pub strip_thickness: f32,
88 pub strip_length: f32,
89 pub strip_corner_radius: f32,
90 pub indicator_radius: f32,
92 pub indicator_outer_stroke_width: f32,
93 pub indicator_inner_stroke_width: f32,
94 pub indicator_outer_color: Color,
95 pub indicator_inner_color: Color,
96 pub strip_thumb_width: f32,
98 pub strip_thumb_height: f32,
99 pub strip_thumb_corner_radius: f32,
100 pub padding: f32,
102 pub gap: f32,
103 pub swatch_size: f32,
105 pub swatch_spacing: f32,
106 pub swatch_corner_radius: f32,
107 pub swatch_selected_stroke_width: f32,
108 pub checker_cell: f32,
110 pub checker_color_a: Color,
111 pub checker_color_b: Color,
112 pub preview_width: f32,
114 pub preview_height: f32,
115 pub preview_corner_radius: f32,
116 pub spinner_field_width: f32,
118 pub hex_field_width: f32,
119}
120
121impl Default for ColorPickerRecipe {
122 fn default() -> Self {
123 Self {
124 canvas_width: CANVAS_WIDTH,
125 canvas_height: CANVAS_HEIGHT,
126 canvas_corner_radius: CANVAS_CORNER_RADIUS,
127 strip_thickness: STRIP_THICKNESS,
128 strip_length: STRIP_LENGTH,
129 strip_corner_radius: STRIP_CORNER_RADIUS,
130 indicator_radius: INDICATOR_RADIUS,
131 indicator_outer_stroke_width: INDICATOR_OUTER_STROKE_WIDTH,
132 indicator_inner_stroke_width: INDICATOR_INNER_STROKE_WIDTH,
133 indicator_outer_color: INDICATOR_OUTER_COLOR,
134 indicator_inner_color: INDICATOR_INNER_COLOR,
135 strip_thumb_width: STRIP_THUMB_WIDTH,
136 strip_thumb_height: STRIP_THUMB_HEIGHT,
137 strip_thumb_corner_radius: STRIP_THUMB_CORNER_RADIUS,
138 padding: PADDING,
139 gap: GAP,
140 swatch_size: SWATCH_SIZE,
141 swatch_spacing: SWATCH_SPACING,
142 swatch_corner_radius: SWATCH_CORNER_RADIUS,
143 swatch_selected_stroke_width: SWATCH_SELECTED_STROKE_WIDTH,
144 checker_cell: CHECKER_CELL,
145 checker_color_a: CHECKER_COLOR_A,
146 checker_color_b: CHECKER_COLOR_B,
147 preview_width: PREVIEW_WIDTH,
148 preview_height: PREVIEW_HEIGHT,
149 preview_corner_radius: PREVIEW_CORNER_RADIUS,
150 spinner_field_width: SPINNER_FIELD_WIDTH,
151 hex_field_width: HEX_FIELD_WIDTH,
152 }
153 }
154}
155
156#[derive(Debug, Default, Clone, Copy)]
158pub struct RecipeColorPickerStyle {
159 pub recipe: ColorPickerRecipe,
160}
161
162impl RecipeColorPickerStyle {
163 pub fn new(recipe: ColorPickerRecipe) -> Self {
164 Self { recipe }
165 }
166}
167
168impl ColorPickerStyle for RecipeColorPickerStyle {
169 fn make_body(&self, cfg: &ColorPickerStyleConfig, ctx: &mut BuildContext) -> WidgetId {
170 let body = match cfg.layout {
171 ColorPickerLayout::Compact => {
172 let mut col = VStack::new()
173 .spacing(self.recipe.gap)
174 .add_child(cfg.top_row);
175 if let Some(hex) = cfg.compact_hex {
176 col = col.add_child(hex);
177 }
178 if let Some(footer) = cfg.footer {
179 col = col.add_child(footer);
180 }
181 ctx.add(col)
182 }
183 ColorPickerLayout::Standard => {
184 let mut col = VStack::new()
185 .spacing(self.recipe.gap)
186 .add_child(cfg.top_row);
187 if let Some(preview) = cfg.preview_row {
188 col = col.add_child(preview);
189 }
190 if let Some(rgb) = cfg.rgb_row {
191 col = col.add_child(rgb);
192 }
193 if let Some(hsv) = cfg.hsv_row {
194 col = col.add_child(hsv);
195 }
196 if let Some(grid) = cfg.swatches {
197 col = col.add_child(grid);
198 }
199 if let Some(footer) = cfg.footer {
200 col = col.add_child(footer);
201 }
202 ctx.add(col)
203 }
204 ColorPickerLayout::Wide => {
205 let mut side_col = VStack::new().spacing(self.recipe.gap);
206 if let Some(preview) = cfg.preview_row {
207 side_col = side_col.add_child(preview);
208 }
209 if let Some(rgb) = cfg.rgb_row {
210 side_col = side_col.add_child(rgb);
211 }
212 if let Some(hsv) = cfg.hsv_row {
213 side_col = side_col.add_child(hsv);
214 }
215 let side_col_id = ctx.add(side_col);
216 let main_row_id = ctx.add(
217 HStack::new()
218 .spacing(self.recipe.gap)
219 .add_child(cfg.top_row)
220 .add_child(side_col_id),
221 );
222 let mut col = VStack::new()
223 .spacing(self.recipe.gap)
224 .add_child(main_row_id);
225 if let Some(grid) = cfg.swatches {
226 col = col.add_child(grid);
227 }
228 if let Some(footer) = cfg.footer {
229 col = col.add_child(footer);
230 }
231 ctx.add(col)
232 }
233 };
234
235 ctx.add(
239 Panel::new()
240 .padding(self.recipe.padding)
241 .border_width(1.0)
242 .child_id(body),
243 )
244 }
245}