1#![allow(non_snake_case)]
2
3use std::rc::Rc;
4use std::sync::atomic::Ordering;
5
6use repose_core::*;
7use repose_ui::{Box, FlowRow, Row, ViewExt, anim::animate_color};
8
9use super::util::{FILTERCHIP_COUNTER, apply_m3_clickable, with_button_semantics};
10use super::*;
11
12#[derive(Clone, Copy, Debug)]
14pub struct ChipColors {
15 pub container_color: Color,
16 pub label_color: Color,
17 pub leading_icon_color: Color,
18 pub trailing_icon_color: Color,
19 pub disabled_container_color: Color,
20 pub disabled_label_color: Color,
21 pub disabled_leading_icon_color: Color,
22 pub disabled_trailing_icon_color: Color,
23 pub selected_container_color: Color,
24 pub selected_label_color: Color,
25 pub selected_leading_icon_color: Color,
26 pub selected_trailing_icon_color: Color,
27 pub disabled_selected_container_color: Color,
28}
29
30impl ChipColors {
31 pub fn container(&self, enabled: bool, selected: bool) -> Color {
32 match (enabled, selected) {
33 (true, true) => self.selected_container_color,
34 (true, false) => self.container_color,
35 (false, true) => self.disabled_selected_container_color,
36 (false, false) => self.disabled_container_color,
37 }
38 }
39 pub fn label(&self, enabled: bool, selected: bool) -> Color {
40 if !enabled {
41 self.disabled_label_color
42 } else if selected {
43 self.selected_label_color
44 } else {
45 self.label_color
46 }
47 }
48 pub fn leading_icon(&self, enabled: bool, selected: bool) -> Color {
49 if !enabled {
50 self.disabled_leading_icon_color
51 } else if selected {
52 self.selected_leading_icon_color
53 } else {
54 self.leading_icon_color
55 }
56 }
57 pub fn trailing_icon(&self, enabled: bool, selected: bool) -> Color {
58 if !enabled {
59 self.disabled_trailing_icon_color
60 } else if selected {
61 self.selected_trailing_icon_color
62 } else {
63 self.trailing_icon_color
64 }
65 }
66}
67
68#[derive(Clone, Copy, Debug)]
70pub struct ChipElevation {
71 pub default: f32,
72 pub hovered: f32,
73 pub focused: f32,
74 pub pressed: f32,
75 pub dragged: f32,
76 pub disabled: f32,
77}
78
79impl ChipElevation {
80 pub fn to_state_elevation(&self) -> StateElevation {
81 StateElevation {
82 default: self.default,
83 hovered: self.hovered,
84 focused: self.focused,
85 pressed: self.pressed,
86 dragged: self.dragged,
87 disabled: self.disabled,
88 }
89 }
90}
91
92impl Default for ChipElevation {
93 fn default() -> Self {
94 Self {
95 default: ChipDefaults::elevation_default(),
96 hovered: ChipDefaults::elevation_hovered(),
97 focused: ChipDefaults::elevation_focused(),
98 pressed: ChipDefaults::elevation_pressed(),
99 dragged: ChipDefaults::elevation_dragged(),
100 disabled: ChipDefaults::elevation_disabled(),
101 }
102 }
103}
104
105#[derive(Clone, Debug)]
107pub struct ChipConfig {
108 pub modifier: Modifier,
109 pub enabled: bool,
110 pub colors: ChipColors,
111 pub elevation: ChipElevation,
112 pub border_width: f32,
113 pub border_color: Color,
114 pub selected_border_color: Color,
115 pub disabled_border_color: Color,
116 pub disabled_selected_border_color: Color,
117 pub shape_radius: f32,
118 pub horizontal_padding: f32,
119 pub interaction_source: Option<MutableInteractionSource>,
120}
121
122impl Default for ChipConfig {
123 fn default() -> Self {
124 Self {
125 modifier: Modifier::new(),
126 enabled: true,
127 colors: ChipColors {
128 container_color: ChipDefaults::container_color(),
129 label_color: ChipDefaults::label_color(),
130 leading_icon_color: ChipDefaults::leading_icon_color(),
131 trailing_icon_color: ChipDefaults::trailing_icon_color(),
132 disabled_container_color: ChipDefaults::disabled_container_color(),
133 disabled_label_color: ChipDefaults::disabled_label_color(),
134 disabled_leading_icon_color: ChipDefaults::disabled_leading_icon_color(),
135 disabled_trailing_icon_color: ChipDefaults::disabled_trailing_icon_color(),
136 selected_container_color: ChipDefaults::selected_container_color(),
137 selected_label_color: ChipDefaults::selected_label_color(),
138 selected_leading_icon_color: ChipDefaults::selected_leading_icon_color(),
139 selected_trailing_icon_color: ChipDefaults::selected_trailing_icon_color(),
140 disabled_selected_container_color: ChipDefaults::disabled_selected_container_color(
141 ),
142 },
143 elevation: ChipElevation::default(),
144 border_width: ChipDefaults::BORDER_WIDTH,
145 border_color: ChipDefaults::border_color(),
146 selected_border_color: ChipDefaults::selected_border_color(),
147 disabled_border_color: ChipDefaults::disabled_border_color(),
148 disabled_selected_border_color: ChipDefaults::disabled_selected_border_color(),
149 shape_radius: ChipDefaults::SHAPE_RADIUS,
150 horizontal_padding: ChipDefaults::HORIZONTAL_PADDING,
151 interaction_source: None,
152 }
153 }
154}
155
156pub fn AssistChip(
158 on_click: impl Fn() + 'static,
159 label: View,
160 leading_icon: Option<View>,
161 trailing_icon: Option<View>,
162 config: ChipConfig,
163) -> View {
164 let th = theme();
165 let is_enabled = config.enabled;
166 let colors = &config.colors;
167 let bg = colors.container(is_enabled, false);
168 let label_color = colors.label(is_enabled, false);
169 let leading_color = colors.leading_icon(is_enabled, false);
170 let trailing_color = colors.trailing_icon(is_enabled, false);
171 let border = if is_enabled {
172 config.border_color
173 } else {
174 config.disabled_border_color
175 };
176 let shape = config.shape_radius;
177 let ch_source: Rc<MutableInteractionSource> = config
178 .interaction_source
179 .clone()
180 .map(Rc::new)
181 .unwrap_or_else(|| remember(MutableInteractionSource::new));
182
183 let mut m = Modifier::new()
184 .flex_shrink(0.0)
185 .min_height(ChipDefaults::HEIGHT)
186 .height(ChipDefaults::HEIGHT)
187 .state_colors(StateColors {
188 default: Color::TRANSPARENT,
189 hovered: Color::TRANSPARENT,
190 focused: Color::TRANSPARENT,
191 pressed: Color::TRANSPARENT,
192 dragged: th.on_surface.with_alpha_f32(0.12),
193 disabled: Color::TRANSPARENT,
194 })
195 .padding_values(PaddingValues {
196 left: config.horizontal_padding,
197 right: config.horizontal_padding,
198 top: 0.0,
199 bottom: 0.0,
200 })
201 .background(bg)
202 .clip_rounded(shape)
203 .align_items(AlignItems::CENTER)
204 .justify_content(JustifyContent::CENTER)
205 .then(config.modifier);
206
207 if config.border_width > 0.0 && border != Color::TRANSPARENT {
208 m = m.border(config.border_width, border, shape);
209 }
210
211 m = apply_m3_clickable(m, &ch_source, label_color, is_enabled, on_click);
212 m = with_button_semantics(m, is_enabled);
213
214 Box(m).child(
215 Row(Modifier::new().align_items(AlignItems::CENTER)).child((
216 leading_icon
217 .map(|v| {
218 Box(Modifier::new().padding_values(PaddingValues {
219 left: 0.0,
220 right: 8.0,
221 top: 0.0,
222 bottom: 0.0,
223 }))
224 .child(with_content_color(leading_color, move || v))
225 })
226 .unwrap_or(Box(Modifier::new())),
227 with_content_color(label_color, move || label),
228 trailing_icon
229 .map(|v| {
230 Box(Modifier::new().padding_values(PaddingValues {
231 left: 8.0,
232 right: 0.0,
233 top: 0.0,
234 bottom: 0.0,
235 }))
236 .child(with_content_color(trailing_color, move || v))
237 })
238 .unwrap_or(Box(Modifier::new())),
239 )),
240 )
241}
242
243pub fn ElevatedAssistChip(
245 on_click: impl Fn() + 'static,
246 label: View,
247 leading_icon: Option<View>,
248 trailing_icon: Option<View>,
249 config: ChipConfig,
250) -> View {
251 let th = theme();
252 let is_enabled = config.enabled;
253 let colors = &config.colors;
254 let bg = colors.container(is_enabled, false);
255 let label_color = colors.label(is_enabled, false);
256 let leading_color = colors.leading_icon(is_enabled, false);
257 let trailing_color = colors.trailing_icon(is_enabled, false);
258 let shape = config.shape_radius;
259 let ch_source: Rc<MutableInteractionSource> = config
260 .interaction_source
261 .clone()
262 .map(Rc::new)
263 .unwrap_or_else(|| remember(MutableInteractionSource::new));
264
265 let mut m = Modifier::new()
266 .flex_shrink(0.0)
267 .min_height(ChipDefaults::HEIGHT)
268 .height(ChipDefaults::HEIGHT)
269 .state_colors(StateColors {
270 default: Color::TRANSPARENT,
271 hovered: Color::TRANSPARENT,
272 focused: Color::TRANSPARENT,
273 pressed: Color::TRANSPARENT,
274 dragged: th.on_surface.with_alpha_f32(0.12),
275 disabled: Color::TRANSPARENT,
276 })
277 .state_elevation(config.elevation.to_state_elevation())
278 .padding_values(PaddingValues {
279 left: config.horizontal_padding,
280 right: config.horizontal_padding,
281 top: 0.0,
282 bottom: 0.0,
283 })
284 .background(bg)
285 .clip_rounded(shape)
286 .align_items(AlignItems::CENTER)
287 .justify_content(JustifyContent::CENTER)
288 .then(config.modifier);
289
290 m = apply_m3_clickable(m, &ch_source, label_color, is_enabled, on_click);
291 m = with_button_semantics(m, is_enabled);
292
293 Box(m).child(
294 Row(Modifier::new().align_items(AlignItems::CENTER)).child((
295 leading_icon
296 .map(|v| {
297 Box(Modifier::new().padding_values(PaddingValues {
298 left: 0.0,
299 right: 8.0,
300 top: 0.0,
301 bottom: 0.0,
302 }))
303 .child(with_content_color(leading_color, move || v))
304 })
305 .unwrap_or(Box(Modifier::new())),
306 with_content_color(label_color, move || label),
307 trailing_icon
308 .map(|v| {
309 Box(Modifier::new().padding_values(PaddingValues {
310 left: 8.0,
311 right: 0.0,
312 top: 0.0,
313 bottom: 0.0,
314 }))
315 .child(with_content_color(trailing_color, move || v))
316 })
317 .unwrap_or(Box(Modifier::new())),
318 )),
319 )
320}
321
322pub fn FilterChip(
323 selected: bool,
324 on_click: impl Fn() + 'static,
325 label: View,
326 leading_icon: Option<View>,
327 trailing_icon: Option<View>,
328 config: ChipConfig,
329) -> View {
330 let th = theme();
331 let id = remember(|| FILTERCHIP_COUNTER.fetch_add(1, Ordering::Relaxed));
332 let spec = th.motion.color;
333 let is_enabled = config.enabled;
334 let colors = &config.colors;
335
336 let bg = animate_color(
337 format!("fc_bg_{}", id),
338 colors.container(is_enabled, selected),
339 spec,
340 );
341 let label_color = animate_color(
342 format!("fc_lc_{}", id),
343 colors.label(is_enabled, selected),
344 spec,
345 );
346 let leading_color = animate_color(
347 format!("fc_lic_{}", id),
348 colors.leading_icon(is_enabled, selected),
349 spec,
350 );
351 let trailing_color = animate_color(
352 format!("fc_tic_{}", id),
353 colors.trailing_icon(is_enabled, selected),
354 spec,
355 );
356 let border = if !is_enabled {
357 if selected {
358 config.disabled_selected_border_color
359 } else {
360 config.disabled_border_color
361 }
362 } else {
363 if selected {
364 config.selected_border_color
365 } else {
366 config.border_color
367 }
368 };
369 let shape = config.shape_radius;
370
371 let ch_source: Rc<MutableInteractionSource> = config
372 .interaction_source
373 .clone()
374 .map(Rc::new)
375 .unwrap_or_else(|| remember(MutableInteractionSource::new));
376
377 let mut m = Modifier::new()
378 .flex_shrink(0.0)
379 .min_height(ChipDefaults::HEIGHT)
380 .height(ChipDefaults::HEIGHT)
381 .state_colors(StateColors {
382 default: Color::TRANSPARENT,
383 hovered: Color::TRANSPARENT,
384 focused: Color::TRANSPARENT,
385 pressed: Color::TRANSPARENT,
386 dragged: th.on_surface.with_alpha_f32(0.12),
387 disabled: Color::TRANSPARENT,
388 })
389 .padding_values(PaddingValues {
390 left: config.horizontal_padding,
391 right: config.horizontal_padding,
392 top: 0.0,
393 bottom: 0.0,
394 })
395 .background(bg)
396 .clip_rounded(shape)
397 .align_items(AlignItems::CENTER)
398 .justify_content(JustifyContent::CENTER)
399 .then(config.modifier);
400
401 if config.border_width > 0.0 && border != Color::TRANSPARENT {
402 m = m.border(config.border_width, border, shape);
403 }
404 m = apply_m3_clickable(m, &ch_source, label_color, is_enabled, on_click);
405 m = with_button_semantics(m, is_enabled);
406
407 Box(m).child(
408 Row(Modifier::new().align_items(AlignItems::CENTER)).child((
409 leading_icon
410 .map(|v| {
411 Box(Modifier::new().padding_values(PaddingValues {
412 left: 0.0,
413 right: 8.0,
414 top: 0.0,
415 bottom: 0.0,
416 }))
417 .child(with_content_color(leading_color, move || v))
418 })
419 .unwrap_or(Box(Modifier::new())),
420 with_content_color(label_color, move || label),
421 trailing_icon
422 .map(|v| {
423 Box(Modifier::new().padding_values(PaddingValues {
424 left: 8.0,
425 right: 0.0,
426 top: 0.0,
427 bottom: 0.0,
428 }))
429 .child(with_content_color(trailing_color, move || v))
430 })
431 .unwrap_or(Box(Modifier::new())),
432 )),
433 )
434}
435
436pub fn ElevatedFilterChip(
438 selected: bool,
439 on_click: impl Fn() + 'static,
440 label: View,
441 leading_icon: Option<View>,
442 trailing_icon: Option<View>,
443 config: ChipConfig,
444) -> View {
445 let th = theme();
446 let id = remember(|| FILTERCHIP_COUNTER.fetch_add(1, Ordering::Relaxed));
447 let spec = th.motion.color;
448 let is_enabled = config.enabled;
449 let colors = &config.colors;
450
451 let bg = animate_color(
452 format!("efc_bg_{}", id),
453 colors.container(is_enabled, selected),
454 spec,
455 );
456 let label_color = animate_color(
457 format!("efc_lc_{}", id),
458 colors.label(is_enabled, selected),
459 spec,
460 );
461 let leading_color = animate_color(
462 format!("efc_lic_{}", id),
463 colors.leading_icon(is_enabled, selected),
464 spec,
465 );
466 let trailing_color = animate_color(
467 format!("efc_tic_{}", id),
468 colors.trailing_icon(is_enabled, selected),
469 spec,
470 );
471 let shape = config.shape_radius;
472
473 let ch_source: Rc<MutableInteractionSource> = config
474 .interaction_source
475 .clone()
476 .map(Rc::new)
477 .unwrap_or_else(|| remember(MutableInteractionSource::new));
478
479 let mut m = Modifier::new()
480 .flex_shrink(0.0)
481 .min_height(ChipDefaults::HEIGHT)
482 .height(ChipDefaults::HEIGHT)
483 .state_colors(StateColors {
484 default: Color::TRANSPARENT,
485 hovered: Color::TRANSPARENT,
486 focused: Color::TRANSPARENT,
487 pressed: Color::TRANSPARENT,
488 dragged: th.on_surface.with_alpha_f32(0.12),
489 disabled: Color::TRANSPARENT,
490 })
491 .state_elevation(config.elevation.to_state_elevation())
492 .padding_values(PaddingValues {
493 left: config.horizontal_padding,
494 right: config.horizontal_padding,
495 top: 0.0,
496 bottom: 0.0,
497 })
498 .background(bg)
499 .clip_rounded(shape)
500 .align_items(AlignItems::CENTER)
501 .justify_content(JustifyContent::CENTER)
502 .then(config.modifier);
503
504 m = apply_m3_clickable(m, &ch_source, label_color, is_enabled, on_click);
505 m = with_button_semantics(m, is_enabled);
506
507 Box(m).child(
508 Row(Modifier::new().align_items(AlignItems::CENTER)).child((
509 leading_icon
510 .map(|v| {
511 Box(Modifier::new().padding_values(PaddingValues {
512 left: 0.0,
513 right: 8.0,
514 top: 0.0,
515 bottom: 0.0,
516 }))
517 .child(with_content_color(leading_color, move || v))
518 })
519 .unwrap_or(Box(Modifier::new())),
520 with_content_color(label_color, move || label),
521 trailing_icon
522 .map(|v| {
523 Box(Modifier::new().padding_values(PaddingValues {
524 left: 8.0,
525 right: 0.0,
526 top: 0.0,
527 bottom: 0.0,
528 }))
529 .child(with_content_color(trailing_color, move || v))
530 })
531 .unwrap_or(Box(Modifier::new())),
532 )),
533 )
534}
535
536pub fn SuggestionChip(
537 on_click: impl Fn() + 'static,
538 label: View,
539 icon: Option<View>,
540 config: ChipConfig,
541) -> View {
542 let th = theme();
543 let is_enabled = config.enabled;
544 let colors = &config.colors;
545 let bg = colors.container(is_enabled, false);
546 let label_color = colors.label(is_enabled, false);
547 let leading_color = colors.leading_icon(is_enabled, false);
548 let border = if is_enabled {
549 config.border_color
550 } else {
551 config.disabled_border_color
552 };
553 let shape = config.shape_radius;
554
555 let ch_source: Rc<MutableInteractionSource> = config
556 .interaction_source
557 .clone()
558 .map(Rc::new)
559 .unwrap_or_else(|| remember(MutableInteractionSource::new));
560
561 let mut m = Modifier::new()
562 .flex_shrink(0.0)
563 .min_height(ChipDefaults::HEIGHT)
564 .height(ChipDefaults::HEIGHT)
565 .state_colors(StateColors {
566 default: Color::TRANSPARENT,
567 hovered: Color::TRANSPARENT,
568 focused: Color::TRANSPARENT,
569 pressed: Color::TRANSPARENT,
570 dragged: th.on_surface.with_alpha_f32(0.12),
571 disabled: Color::TRANSPARENT,
572 })
573 .padding_values(PaddingValues {
574 left: config.horizontal_padding,
575 right: config.horizontal_padding,
576 top: 0.0,
577 bottom: 0.0,
578 })
579 .background(bg)
580 .clip_rounded(shape)
581 .align_items(AlignItems::CENTER)
582 .justify_content(JustifyContent::CENTER)
583 .then(config.modifier);
584
585 if config.border_width > 0.0 && border != Color::TRANSPARENT {
586 m = m.border(config.border_width, border, shape);
587 }
588 m = apply_m3_clickable(m, &ch_source, label_color, is_enabled, on_click);
589 m = with_button_semantics(m, is_enabled);
590
591 Box(m).child(
592 Row(Modifier::new().align_items(AlignItems::CENTER)).child((
593 icon.map(|v| {
594 Box(Modifier::new().padding_values(PaddingValues {
595 left: 0.0,
596 right: 8.0,
597 top: 0.0,
598 bottom: 0.0,
599 }))
600 .child(with_content_color(leading_color, move || v))
601 })
602 .unwrap_or(Box(Modifier::new())),
603 with_content_color(label_color, move || label),
604 )),
605 )
606}
607
608pub fn ElevatedSuggestionChip(
610 on_click: impl Fn() + 'static,
611 label: View,
612 icon: Option<View>,
613 config: ChipConfig,
614) -> View {
615 let th = theme();
616 let is_enabled = config.enabled;
617 let colors = &config.colors;
618 let bg = colors.container(is_enabled, false);
619 let label_color = colors.label(is_enabled, false);
620 let leading_color = colors.leading_icon(is_enabled, false);
621 let shape = config.shape_radius;
622
623 let ch_source: Rc<MutableInteractionSource> = config
624 .interaction_source
625 .clone()
626 .map(Rc::new)
627 .unwrap_or_else(|| remember(MutableInteractionSource::new));
628
629 let mut m = Modifier::new()
630 .flex_shrink(0.0)
631 .min_height(ChipDefaults::HEIGHT)
632 .height(ChipDefaults::HEIGHT)
633 .state_colors(StateColors {
634 default: Color::TRANSPARENT,
635 hovered: Color::TRANSPARENT,
636 focused: Color::TRANSPARENT,
637 pressed: Color::TRANSPARENT,
638 dragged: th.on_surface.with_alpha_f32(0.12),
639 disabled: Color::TRANSPARENT,
640 })
641 .state_elevation(config.elevation.to_state_elevation())
642 .padding_values(PaddingValues {
643 left: config.horizontal_padding,
644 right: config.horizontal_padding,
645 top: 0.0,
646 bottom: 0.0,
647 })
648 .background(bg)
649 .clip_rounded(shape)
650 .align_items(AlignItems::CENTER)
651 .justify_content(JustifyContent::CENTER)
652 .then(config.modifier);
653
654 m = apply_m3_clickable(m, &ch_source, label_color, is_enabled, on_click);
655 m = with_button_semantics(m, is_enabled);
656
657 Box(m).child(
658 Row(Modifier::new().align_items(AlignItems::CENTER)).child((
659 icon.map(|v| {
660 Box(Modifier::new().padding_values(PaddingValues {
661 left: 0.0,
662 right: 8.0,
663 top: 0.0,
664 bottom: 0.0,
665 }))
666 .child(with_content_color(leading_color, move || v))
667 })
668 .unwrap_or(Box(Modifier::new())),
669 with_content_color(label_color, move || label),
670 )),
671 )
672}
673
674pub fn InputChip(
675 selected: bool,
676 on_click: impl Fn() + 'static,
677 label: View,
678 leading_icon: Option<View>,
679 avatar: Option<View>,
680 trailing_icon: Option<View>,
681 config: ChipConfig,
682) -> View {
683 let th = theme();
684 let id = remember(|| FILTERCHIP_COUNTER.fetch_add(1, Ordering::Relaxed));
685 let spec = th.motion.color;
686 let is_enabled = config.enabled;
687 let colors = &config.colors;
688
689 let bg = animate_color(
690 format!("ic_bg_{}", id),
691 colors.container(is_enabled, selected),
692 spec,
693 );
694 let label_color = animate_color(
695 format!("ic_lc_{}", id),
696 colors.label(is_enabled, selected),
697 spec,
698 );
699 let leading_color = animate_color(
700 format!("ic_lic_{}", id),
701 colors.leading_icon(is_enabled, selected),
702 spec,
703 );
704 let trailing_color = animate_color(
705 format!("ic_tic_{}", id),
706 colors.trailing_icon(is_enabled, selected),
707 spec,
708 );
709 let border = if !is_enabled {
710 if selected {
711 config.disabled_selected_border_color
712 } else {
713 config.disabled_border_color
714 }
715 } else {
716 if selected {
717 config.selected_border_color
718 } else {
719 config.border_color
720 }
721 };
722 let shape = config.shape_radius;
723
724 let ch_source: Rc<MutableInteractionSource> = config
725 .interaction_source
726 .clone()
727 .map(Rc::new)
728 .unwrap_or_else(|| remember(MutableInteractionSource::new));
729
730 let mut m = Modifier::new()
731 .flex_shrink(0.0)
732 .min_height(ChipDefaults::HEIGHT)
733 .height(ChipDefaults::HEIGHT)
734 .state_colors(StateColors {
735 default: Color::TRANSPARENT,
736 hovered: Color::TRANSPARENT,
737 focused: Color::TRANSPARENT,
738 pressed: Color::TRANSPARENT,
739 dragged: th.on_surface.with_alpha_f32(0.12),
740 disabled: Color::TRANSPARENT,
741 })
742 .padding_values(PaddingValues {
743 left: config.horizontal_padding,
744 right: config.horizontal_padding,
745 top: 0.0,
746 bottom: 0.0,
747 })
748 .background(bg)
749 .clip_rounded(shape)
750 .align_items(AlignItems::CENTER)
751 .justify_content(JustifyContent::CENTER)
752 .then(config.modifier);
753
754 if config.border_width > 0.0 && border != Color::TRANSPARENT {
755 m = m.border(config.border_width, border, shape);
756 }
757 m = apply_m3_clickable(m, &ch_source, label_color, is_enabled, on_click);
758 m = with_button_semantics(m, is_enabled);
759
760 Box(m).child(
761 Row(Modifier::new().align_items(AlignItems::CENTER)).child((
762 avatar
763 .or(leading_icon)
764 .map(|v| {
765 Box(Modifier::new().padding_values(PaddingValues {
766 left: 0.0,
767 right: 8.0,
768 top: 0.0,
769 bottom: 0.0,
770 }))
771 .child(with_content_color(leading_color, move || v))
772 })
773 .unwrap_or(Box(Modifier::new())),
774 with_content_color(label_color, move || label),
775 trailing_icon
776 .map(|v| {
777 Box(Modifier::new().padding_values(PaddingValues {
778 left: 8.0,
779 right: 0.0,
780 top: 0.0,
781 bottom: 0.0,
782 }))
783 .child(with_content_color(trailing_color, move || v))
784 })
785 .unwrap_or(Box(Modifier::new())),
786 )),
787 )
788}
789
790pub fn chip_group_flow(modifier: Modifier, children: impl repose_ui::IntoChildren) -> View {
794 FlowRow(
795 Modifier::new()
796 .fill_max_width()
797 .gap(8.0)
798 .align_items(AlignItems::CENTER)
799 .then(modifier),
800 )
801 .child(children)
802}
803
804pub fn FilterChipGroup(modifier: Modifier, children: impl repose_ui::IntoChildren) -> View {
806 chip_group_flow(modifier, children)
807}
808
809pub fn ElevatedFilterChipGroup(modifier: Modifier, children: impl repose_ui::IntoChildren) -> View {
811 chip_group_flow(modifier, children)
812}
813
814pub fn AssistChipGroup(modifier: Modifier, children: impl repose_ui::IntoChildren) -> View {
816 chip_group_flow(modifier, children)
817}
818
819pub fn ElevatedAssistChipGroup(modifier: Modifier, children: impl repose_ui::IntoChildren) -> View {
822 chip_group_flow(modifier, children)
823}
824
825pub fn SuggestionChipGroup(modifier: Modifier, children: impl repose_ui::IntoChildren) -> View {
827 chip_group_flow(modifier, children)
828}
829
830pub fn ElevatedSuggestionChipGroup(
832 modifier: Modifier,
833 children: impl repose_ui::IntoChildren,
834) -> View {
835 chip_group_flow(modifier, children)
836}
837
838pub fn InputChipGroup(modifier: Modifier, children: impl repose_ui::IntoChildren) -> View {
840 chip_group_flow(modifier, children)
841}