1use std::rc::Rc;
2
3use gpui::{AnyView, ClickEvent, relative};
4
5use crate::{ButtonLike, ButtonLikeRounding, ElevationIndex, TintColor, Tooltip, prelude::*};
6
7/// The position of a [`ToggleButton`] within a group of buttons.
8#[derive(Debug, PartialEq, Eq, Clone, Copy)]
9pub enum ToggleButtonPosition {
10 /// The toggle button is first in the group.
11 First,
12
13 /// The toggle button is in the middle of the group (i.e., it is not the first or last toggle button).
14 Middle,
15
16 /// The toggle button is last in the group.
17 Last,
18}
19
20#[derive(IntoElement, RegisterComponent)]
21pub struct ToggleButton {
22 base: ButtonLike,
23 position_in_group: Option<ToggleButtonPosition>,
24 label: SharedString,
25 label_color: Option<Color>,
26}
27
28impl ToggleButton {
29 pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
30 Self {
31 base: ButtonLike::new(id),
32 position_in_group: None,
33 label: label.into(),
34 label_color: None,
35 }
36 }
37
38 pub fn color(mut self, label_color: impl Into<Option<Color>>) -> Self {
39 self.label_color = label_color.into();
40 self
41 }
42
43 pub fn position_in_group(mut self, position: ToggleButtonPosition) -> Self {
44 self.position_in_group = Some(position);
45 self
46 }
47
48 pub fn first(self) -> Self {
49 self.position_in_group(ToggleButtonPosition::First)
50 }
51
52 pub fn middle(self) -> Self {
53 self.position_in_group(ToggleButtonPosition::Middle)
54 }
55
56 pub fn last(self) -> Self {
57 self.position_in_group(ToggleButtonPosition::Last)
58 }
59}
60
61impl Toggleable for ToggleButton {
62 fn toggle_state(mut self, selected: bool) -> Self {
63 self.base = self.base.toggle_state(selected);
64 self
65 }
66}
67
68impl SelectableButton for ToggleButton {
69 fn selected_style(mut self, style: ButtonStyle) -> Self {
70 self.base.selected_style = Some(style);
71 self
72 }
73}
74
75impl FixedWidth for ToggleButton {
76 fn width(mut self, width: impl Into<DefiniteLength>) -> Self {
77 self.base.width = Some(width.into());
78 self
79 }
80
81 fn full_width(mut self) -> Self {
82 self.base.width = Some(relative(1.));
83 self
84 }
85}
86
87impl Disableable for ToggleButton {
88 fn disabled(mut self, disabled: bool) -> Self {
89 self.base = self.base.disabled(disabled);
90 self
91 }
92}
93
94impl Clickable for ToggleButton {
95 fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
96 self.base = self.base.on_click(handler);
97 self
98 }
99
100 fn cursor_style(mut self, cursor_style: gpui::CursorStyle) -> Self {
101 self.base = self.base.cursor_style(cursor_style);
102 self
103 }
104}
105
106impl ButtonCommon for ToggleButton {
107 fn id(&self) -> &ElementId {
108 self.base.id()
109 }
110
111 fn style(mut self, style: ButtonStyle) -> Self {
112 self.base = self.base.style(style);
113 self
114 }
115
116 fn size(mut self, size: ButtonSize) -> Self {
117 self.base = self.base.size(size);
118 self
119 }
120
121 fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
122 self.base = self.base.tooltip(tooltip);
123 self
124 }
125
126 fn tab_index(mut self, tab_index: impl Into<isize>) -> Self {
127 self.base = self.base.tab_index(tab_index);
128 self
129 }
130
131 fn layer(mut self, elevation: ElevationIndex) -> Self {
132 self.base = self.base.layer(elevation);
133 self
134 }
135
136 fn track_focus(mut self, focus_handle: &gpui::FocusHandle) -> Self {
137 self.base = self.base.track_focus(focus_handle);
138 self
139 }
140}
141
142impl RenderOnce for ToggleButton {
143 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
144 let is_disabled = self.base.disabled;
145 let is_selected = self.base.selected;
146
147 let label_color = if is_disabled {
148 Color::Disabled
149 } else if is_selected {
150 Color::Selected
151 } else {
152 self.label_color.unwrap_or_default()
153 };
154
155 self.base
156 .when_some(self.position_in_group, |this, position| match position {
157 ToggleButtonPosition::First => this.rounding(ButtonLikeRounding::Left),
158 ToggleButtonPosition::Middle => this.rounding(None),
159 ToggleButtonPosition::Last => this.rounding(ButtonLikeRounding::Right),
160 })
161 .child(
162 Label::new(self.label)
163 .color(label_color)
164 .line_height_style(LineHeightStyle::UiLabel),
165 )
166 }
167}
168
169impl Component for ToggleButton {
170 fn scope() -> ComponentScope {
171 ComponentScope::Input
172 }
173
174 fn sort_name() -> &'static str {
175 "ButtonC"
176 }
177
178 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
179 Some(
180 v_flex()
181 .gap_6()
182 .children(vec![
183 example_group_with_title(
184 "Button Styles",
185 vec![
186 single_example(
187 "Off",
188 ToggleButton::new("off", "Off")
189 .layer(ElevationIndex::Background)
190 .style(ButtonStyle::Filled)
191 .into_any_element(),
192 ),
193 single_example(
194 "On",
195 ToggleButton::new("on", "On")
196 .layer(ElevationIndex::Background)
197 .toggle_state(true)
198 .style(ButtonStyle::Filled)
199 .into_any_element(),
200 ),
201 single_example(
202 "Off – Disabled",
203 ToggleButton::new("disabled_off", "Disabled Off")
204 .layer(ElevationIndex::Background)
205 .disabled(true)
206 .style(ButtonStyle::Filled)
207 .into_any_element(),
208 ),
209 single_example(
210 "On – Disabled",
211 ToggleButton::new("disabled_on", "Disabled On")
212 .layer(ElevationIndex::Background)
213 .disabled(true)
214 .toggle_state(true)
215 .style(ButtonStyle::Filled)
216 .into_any_element(),
217 ),
218 ],
219 ),
220 example_group_with_title(
221 "Button Group",
222 vec![
223 single_example(
224 "Three Buttons",
225 h_flex()
226 .child(
227 ToggleButton::new("three_btn_first", "First")
228 .layer(ElevationIndex::Background)
229 .style(ButtonStyle::Filled)
230 .first()
231 .into_any_element(),
232 )
233 .child(
234 ToggleButton::new("three_btn_middle", "Middle")
235 .layer(ElevationIndex::Background)
236 .style(ButtonStyle::Filled)
237 .middle()
238 .toggle_state(true)
239 .into_any_element(),
240 )
241 .child(
242 ToggleButton::new("three_btn_last", "Last")
243 .layer(ElevationIndex::Background)
244 .style(ButtonStyle::Filled)
245 .last()
246 .into_any_element(),
247 )
248 .into_any_element(),
249 ),
250 single_example(
251 "Two Buttons",
252 h_flex()
253 .child(
254 ToggleButton::new("two_btn_first", "First")
255 .layer(ElevationIndex::Background)
256 .style(ButtonStyle::Filled)
257 .first()
258 .into_any_element(),
259 )
260 .child(
261 ToggleButton::new("two_btn_last", "Last")
262 .layer(ElevationIndex::Background)
263 .style(ButtonStyle::Filled)
264 .last()
265 .into_any_element(),
266 )
267 .into_any_element(),
268 ),
269 ],
270 ),
271 example_group_with_title(
272 "Alternate Sizes",
273 vec![
274 single_example(
275 "None",
276 ToggleButton::new("none", "None")
277 .layer(ElevationIndex::Background)
278 .style(ButtonStyle::Filled)
279 .size(ButtonSize::None)
280 .into_any_element(),
281 ),
282 single_example(
283 "Compact",
284 ToggleButton::new("compact", "Compact")
285 .layer(ElevationIndex::Background)
286 .style(ButtonStyle::Filled)
287 .size(ButtonSize::Compact)
288 .into_any_element(),
289 ),
290 single_example(
291 "Large",
292 ToggleButton::new("large", "Large")
293 .layer(ElevationIndex::Background)
294 .style(ButtonStyle::Filled)
295 .size(ButtonSize::Large)
296 .into_any_element(),
297 ),
298 ],
299 ),
300 ])
301 .into_any_element(),
302 )
303 }
304}
305
306pub struct ButtonConfiguration {
307 label: SharedString,
308 icon: Option<IconName>,
309 on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
310 selected: bool,
311 tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
312}
313
314mod private {
315 pub trait ToggleButtonStyle {}
316}
317
318pub trait ButtonBuilder: 'static + private::ToggleButtonStyle {
319 fn into_configuration(self) -> ButtonConfiguration;
320}
321
322pub struct ToggleButtonSimple {
323 label: SharedString,
324 on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
325 selected: bool,
326 tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
327}
328
329impl ToggleButtonSimple {
330 pub fn new(
331 label: impl Into<SharedString>,
332 on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
333 ) -> Self {
334 Self {
335 label: label.into(),
336 on_click: Box::new(on_click),
337 selected: false,
338 tooltip: None,
339 }
340 }
341
342 pub fn selected(mut self, selected: bool) -> Self {
343 self.selected = selected;
344 self
345 }
346
347 pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
348 self.tooltip = Some(Rc::new(tooltip));
349 self
350 }
351}
352
353impl private::ToggleButtonStyle for ToggleButtonSimple {}
354
355impl ButtonBuilder for ToggleButtonSimple {
356 fn into_configuration(self) -> ButtonConfiguration {
357 ButtonConfiguration {
358 label: self.label,
359 icon: None,
360 on_click: self.on_click,
361 selected: self.selected,
362 tooltip: self.tooltip,
363 }
364 }
365}
366
367pub struct ToggleButtonWithIcon {
368 label: SharedString,
369 icon: IconName,
370 on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
371 selected: bool,
372 tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
373}
374
375impl ToggleButtonWithIcon {
376 pub fn new(
377 label: impl Into<SharedString>,
378 icon: IconName,
379 on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
380 ) -> Self {
381 Self {
382 label: label.into(),
383 icon,
384 on_click: Box::new(on_click),
385 selected: false,
386 tooltip: None,
387 }
388 }
389
390 pub fn selected(mut self, selected: bool) -> Self {
391 self.selected = selected;
392 self
393 }
394
395 pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
396 self.tooltip = Some(Rc::new(tooltip));
397 self
398 }
399}
400
401impl private::ToggleButtonStyle for ToggleButtonWithIcon {}
402
403impl ButtonBuilder for ToggleButtonWithIcon {
404 fn into_configuration(self) -> ButtonConfiguration {
405 ButtonConfiguration {
406 label: self.label,
407 icon: Some(self.icon),
408 on_click: self.on_click,
409 selected: self.selected,
410 tooltip: self.tooltip,
411 }
412 }
413}
414
415#[derive(Clone, Copy, PartialEq)]
416pub enum ToggleButtonGroupStyle {
417 Transparent,
418 Filled,
419 Outlined,
420}
421
422#[derive(Clone, Copy, PartialEq)]
423pub enum ToggleButtonGroupSize {
424 Default,
425 Medium,
426}
427
428#[derive(IntoElement)]
429pub struct ToggleButtonGroup<T, const COLS: usize = 3, const ROWS: usize = 1>
430where
431 T: ButtonBuilder,
432{
433 group_name: SharedString,
434 rows: [[T; COLS]; ROWS],
435 style: ToggleButtonGroupStyle,
436 size: ToggleButtonGroupSize,
437 group_width: Option<DefiniteLength>,
438 selected_index: usize,
439 tab_index: Option<isize>,
440}
441
442impl<T: ButtonBuilder, const COLS: usize> ToggleButtonGroup<T, COLS> {
443 pub fn single_row(group_name: impl Into<SharedString>, buttons: [T; COLS]) -> Self {
444 Self {
445 group_name: group_name.into(),
446 rows: [buttons],
447 style: ToggleButtonGroupStyle::Transparent,
448 size: ToggleButtonGroupSize::Default,
449 group_width: None,
450 selected_index: 0,
451 tab_index: None,
452 }
453 }
454}
455
456impl<T: ButtonBuilder, const COLS: usize> ToggleButtonGroup<T, COLS, 2> {
457 pub fn two_rows(
458 group_name: impl Into<SharedString>,
459 first_row: [T; COLS],
460 second_row: [T; COLS],
461 ) -> Self {
462 Self {
463 group_name: group_name.into(),
464 rows: [first_row, second_row],
465 style: ToggleButtonGroupStyle::Transparent,
466 size: ToggleButtonGroupSize::Default,
467 group_width: None,
468 selected_index: 0,
469 tab_index: None,
470 }
471 }
472}
473
474impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> ToggleButtonGroup<T, COLS, ROWS> {
475 pub fn style(mut self, style: ToggleButtonGroupStyle) -> Self {
476 self.style = style;
477 self
478 }
479
480 pub fn size(mut self, size: ToggleButtonGroupSize) -> Self {
481 self.size = size;
482 self
483 }
484
485 pub fn selected_index(mut self, index: usize) -> Self {
486 self.selected_index = index;
487 self
488 }
489
490 /// Sets the tab index for the toggle button group.
491 /// The tab index is set to the initial value provided, then the
492 /// value is incremented by the number of buttons in the group.
493 pub fn tab_index(mut self, tab_index: &mut isize) -> Self {
494 self.tab_index = Some(*tab_index);
495 *tab_index += (COLS * ROWS) as isize;
496 self
497 }
498
499 const fn button_width() -> DefiniteLength {
500 relative(1. / COLS as f32)
501 }
502}
503
504impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> FixedWidth
505 for ToggleButtonGroup<T, COLS, ROWS>
506{
507 fn width(mut self, width: impl Into<DefiniteLength>) -> Self {
508 self.group_width = Some(width.into());
509 self
510 }
511
512 fn full_width(mut self) -> Self {
513 self.group_width = Some(relative(1.));
514 self
515 }
516}
517
518impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> RenderOnce
519 for ToggleButtonGroup<T, COLS, ROWS>
520{
521 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
522 let entries =
523 self.rows.into_iter().enumerate().map(|(row_index, row)| {
524 let group_name = self.group_name.clone();
525 row.into_iter().enumerate().map(move |(col_index, button)| {
526 let ButtonConfiguration {
527 label,
528 icon,
529 on_click,
530 selected,
531 tooltip,
532 } = button.into_configuration();
533
534 let entry_index = row_index * COLS + col_index;
535
536 ButtonLike::new((group_name.clone(), entry_index))
537 .full_width()
538 .rounding(None)
539 .when_some(self.tab_index, |this, tab_index| {
540 this.tab_index(tab_index + entry_index as isize)
541 })
542 .when(entry_index == self.selected_index || selected, |this| {
543 this.toggle_state(true)
544 .selected_style(ButtonStyle::Tinted(TintColor::Accent))
545 })
546 .when(self.style == ToggleButtonGroupStyle::Filled, |button| {
547 button.style(ButtonStyle::Filled)
548 })
549 .when(self.size == ToggleButtonGroupSize::Medium, |button| {
550 button.size(ButtonSize::Medium)
551 })
552 .child(
553 h_flex()
554 .w_full()
555 .gap_1p5()
556 .px_3()
557 .py_1()
558 .justify_center()
559 .when_some(icon, |this, icon| {
560 this.py_2()
561 .child(Icon::new(icon).size(IconSize::XSmall).map(|this| {
562 if entry_index == self.selected_index || selected {
563 this.color(Color::Accent)
564 } else {
565 this.color(Color::Muted)
566 }
567 }))
568 })
569 .child(Label::new(label).size(LabelSize::Small).when(
570 entry_index == self.selected_index || selected,
571 |this| this.color(Color::Accent),
572 )),
573 )
574 .when_some(tooltip, |this, tooltip| {
575 this.tooltip(move |window, cx| tooltip(window, cx))
576 })
577 .on_click(on_click)
578 .into_any_element()
579 })
580 });
581
582 let border_color = cx.theme().colors().border.opacity(0.6);
583 let is_outlined_or_filled = self.style == ToggleButtonGroupStyle::Outlined
584 || self.style == ToggleButtonGroupStyle::Filled;
585 let is_transparent = self.style == ToggleButtonGroupStyle::Transparent;
586
587 v_flex()
588 .map(|this| {
589 if let Some(width) = self.group_width {
590 this.w(width)
591 } else {
592 this.w_full()
593 }
594 })
595 .rounded_md()
596 .overflow_hidden()
597 .map(|this| {
598 if is_transparent {
599 this.gap_px()
600 } else {
601 this.border_1().border_color(border_color)
602 }
603 })
604 .children(entries.enumerate().map(|(row_index, row)| {
605 let last_row = row_index == ROWS - 1;
606 h_flex()
607 .when(!is_outlined_or_filled, |this| this.gap_px())
608 .when(is_outlined_or_filled && !last_row, |this| {
609 this.border_b_1().border_color(border_color)
610 })
611 .children(row.enumerate().map(|(item_index, item)| {
612 let last_item = item_index == COLS - 1;
613 div()
614 .when(is_outlined_or_filled && !last_item, |this| {
615 this.border_r_1().border_color(border_color)
616 })
617 .w(Self::button_width())
618 .overflow_hidden()
619 .child(item)
620 }))
621 }))
622 }
623}
624
625fn register_toggle_button_group() {
626 component::register_component::<ToggleButtonGroup<ToggleButtonSimple>>();
627}
628
629component::__private::inventory::submit! {
630 component::ComponentFn::new(register_toggle_button_group)
631}
632
633impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> Component
634 for ToggleButtonGroup<T, COLS, ROWS>
635{
636 fn name() -> &'static str {
637 "ToggleButtonGroup"
638 }
639
640 fn scope() -> ComponentScope {
641 ComponentScope::Input
642 }
643
644 fn sort_name() -> &'static str {
645 "ButtonG"
646 }
647
648 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
649 Some(
650 v_flex()
651 .gap_6()
652 .children(vec![example_group_with_title(
653 "Transparent Variant",
654 vec![
655 single_example(
656 "Single Row Group",
657 ToggleButtonGroup::single_row(
658 "single_row_test",
659 [
660 ToggleButtonSimple::new("First", |_, _, _| {}),
661 ToggleButtonSimple::new("Second", |_, _, _| {}),
662 ToggleButtonSimple::new("Third", |_, _, _| {}),
663 ],
664 )
665 .selected_index(1)
666 .into_any_element(),
667 ),
668 single_example(
669 "Single Row Group with icons",
670 ToggleButtonGroup::single_row(
671 "single_row_test_icon",
672 [
673 ToggleButtonWithIcon::new(
674 "First",
675 IconName::AiZed,
676 |_, _, _| {},
677 ),
678 ToggleButtonWithIcon::new(
679 "Second",
680 IconName::AiZed,
681 |_, _, _| {},
682 ),
683 ToggleButtonWithIcon::new(
684 "Third",
685 IconName::AiZed,
686 |_, _, _| {},
687 ),
688 ],
689 )
690 .selected_index(1)
691 .into_any_element(),
692 ),
693 single_example(
694 "Multiple Row Group",
695 ToggleButtonGroup::two_rows(
696 "multiple_row_test",
697 [
698 ToggleButtonSimple::new("First", |_, _, _| {}),
699 ToggleButtonSimple::new("Second", |_, _, _| {}),
700 ToggleButtonSimple::new("Third", |_, _, _| {}),
701 ],
702 [
703 ToggleButtonSimple::new("Fourth", |_, _, _| {}),
704 ToggleButtonSimple::new("Fifth", |_, _, _| {}),
705 ToggleButtonSimple::new("Sixth", |_, _, _| {}),
706 ],
707 )
708 .selected_index(3)
709 .into_any_element(),
710 ),
711 single_example(
712 "Multiple Row Group with Icons",
713 ToggleButtonGroup::two_rows(
714 "multiple_row_test_icons",
715 [
716 ToggleButtonWithIcon::new(
717 "First",
718 IconName::AiZed,
719 |_, _, _| {},
720 ),
721 ToggleButtonWithIcon::new(
722 "Second",
723 IconName::AiZed,
724 |_, _, _| {},
725 ),
726 ToggleButtonWithIcon::new(
727 "Third",
728 IconName::AiZed,
729 |_, _, _| {},
730 ),
731 ],
732 [
733 ToggleButtonWithIcon::new(
734 "Fourth",
735 IconName::AiZed,
736 |_, _, _| {},
737 ),
738 ToggleButtonWithIcon::new(
739 "Fifth",
740 IconName::AiZed,
741 |_, _, _| {},
742 ),
743 ToggleButtonWithIcon::new(
744 "Sixth",
745 IconName::AiZed,
746 |_, _, _| {},
747 ),
748 ],
749 )
750 .selected_index(3)
751 .into_any_element(),
752 ),
753 ],
754 )])
755 .children(vec![example_group_with_title(
756 "Outlined Variant",
757 vec![
758 single_example(
759 "Single Row Group",
760 ToggleButtonGroup::single_row(
761 "single_row_test_outline",
762 [
763 ToggleButtonSimple::new("First", |_, _, _| {}),
764 ToggleButtonSimple::new("Second", |_, _, _| {}),
765 ToggleButtonSimple::new("Third", |_, _, _| {}),
766 ],
767 )
768 .selected_index(1)
769 .style(ToggleButtonGroupStyle::Outlined)
770 .into_any_element(),
771 ),
772 single_example(
773 "Single Row Group with icons",
774 ToggleButtonGroup::single_row(
775 "single_row_test_icon_outlined",
776 [
777 ToggleButtonWithIcon::new(
778 "First",
779 IconName::AiZed,
780 |_, _, _| {},
781 ),
782 ToggleButtonWithIcon::new(
783 "Second",
784 IconName::AiZed,
785 |_, _, _| {},
786 ),
787 ToggleButtonWithIcon::new(
788 "Third",
789 IconName::AiZed,
790 |_, _, _| {},
791 ),
792 ],
793 )
794 .selected_index(1)
795 .style(ToggleButtonGroupStyle::Outlined)
796 .into_any_element(),
797 ),
798 single_example(
799 "Multiple Row Group",
800 ToggleButtonGroup::two_rows(
801 "multiple_row_test",
802 [
803 ToggleButtonSimple::new("First", |_, _, _| {}),
804 ToggleButtonSimple::new("Second", |_, _, _| {}),
805 ToggleButtonSimple::new("Third", |_, _, _| {}),
806 ],
807 [
808 ToggleButtonSimple::new("Fourth", |_, _, _| {}),
809 ToggleButtonSimple::new("Fifth", |_, _, _| {}),
810 ToggleButtonSimple::new("Sixth", |_, _, _| {}),
811 ],
812 )
813 .selected_index(3)
814 .style(ToggleButtonGroupStyle::Outlined)
815 .into_any_element(),
816 ),
817 single_example(
818 "Multiple Row Group with Icons",
819 ToggleButtonGroup::two_rows(
820 "multiple_row_test",
821 [
822 ToggleButtonWithIcon::new(
823 "First",
824 IconName::AiZed,
825 |_, _, _| {},
826 ),
827 ToggleButtonWithIcon::new(
828 "Second",
829 IconName::AiZed,
830 |_, _, _| {},
831 ),
832 ToggleButtonWithIcon::new(
833 "Third",
834 IconName::AiZed,
835 |_, _, _| {},
836 ),
837 ],
838 [
839 ToggleButtonWithIcon::new(
840 "Fourth",
841 IconName::AiZed,
842 |_, _, _| {},
843 ),
844 ToggleButtonWithIcon::new(
845 "Fifth",
846 IconName::AiZed,
847 |_, _, _| {},
848 ),
849 ToggleButtonWithIcon::new(
850 "Sixth",
851 IconName::AiZed,
852 |_, _, _| {},
853 ),
854 ],
855 )
856 .selected_index(3)
857 .style(ToggleButtonGroupStyle::Outlined)
858 .into_any_element(),
859 ),
860 ],
861 )])
862 .children(vec![example_group_with_title(
863 "Filled Variant",
864 vec![
865 single_example(
866 "Single Row Group",
867 ToggleButtonGroup::single_row(
868 "single_row_test_outline",
869 [
870 ToggleButtonSimple::new("First", |_, _, _| {}),
871 ToggleButtonSimple::new("Second", |_, _, _| {}),
872 ToggleButtonSimple::new("Third", |_, _, _| {}),
873 ],
874 )
875 .selected_index(2)
876 .style(ToggleButtonGroupStyle::Filled)
877 .into_any_element(),
878 ),
879 single_example(
880 "Single Row Group with icons",
881 ToggleButtonGroup::single_row(
882 "single_row_test_icon_outlined",
883 [
884 ToggleButtonWithIcon::new(
885 "First",
886 IconName::AiZed,
887 |_, _, _| {},
888 ),
889 ToggleButtonWithIcon::new(
890 "Second",
891 IconName::AiZed,
892 |_, _, _| {},
893 ),
894 ToggleButtonWithIcon::new(
895 "Third",
896 IconName::AiZed,
897 |_, _, _| {},
898 ),
899 ],
900 )
901 .selected_index(1)
902 .style(ToggleButtonGroupStyle::Filled)
903 .into_any_element(),
904 ),
905 single_example(
906 "Multiple Row Group",
907 ToggleButtonGroup::two_rows(
908 "multiple_row_test",
909 [
910 ToggleButtonSimple::new("First", |_, _, _| {}),
911 ToggleButtonSimple::new("Second", |_, _, _| {}),
912 ToggleButtonSimple::new("Third", |_, _, _| {}),
913 ],
914 [
915 ToggleButtonSimple::new("Fourth", |_, _, _| {}),
916 ToggleButtonSimple::new("Fifth", |_, _, _| {}),
917 ToggleButtonSimple::new("Sixth", |_, _, _| {}),
918 ],
919 )
920 .selected_index(3)
921 .width(rems_from_px(100.))
922 .style(ToggleButtonGroupStyle::Filled)
923 .into_any_element(),
924 ),
925 single_example(
926 "Multiple Row Group with Icons",
927 ToggleButtonGroup::two_rows(
928 "multiple_row_test",
929 [
930 ToggleButtonWithIcon::new(
931 "First",
932 IconName::AiZed,
933 |_, _, _| {},
934 ),
935 ToggleButtonWithIcon::new(
936 "Second",
937 IconName::AiZed,
938 |_, _, _| {},
939 ),
940 ToggleButtonWithIcon::new(
941 "Third",
942 IconName::AiZed,
943 |_, _, _| {},
944 ),
945 ],
946 [
947 ToggleButtonWithIcon::new(
948 "Fourth",
949 IconName::AiZed,
950 |_, _, _| {},
951 ),
952 ToggleButtonWithIcon::new(
953 "Fifth",
954 IconName::AiZed,
955 |_, _, _| {},
956 ),
957 ToggleButtonWithIcon::new(
958 "Sixth",
959 IconName::AiZed,
960 |_, _, _| {},
961 ),
962 ],
963 )
964 .selected_index(3)
965 .width(rems_from_px(100.))
966 .style(ToggleButtonGroupStyle::Filled)
967 .into_any_element(),
968 ),
969 ],
970 )])
971 .children(vec![single_example(
972 "With Tooltips",
973 ToggleButtonGroup::single_row(
974 "with_tooltips",
975 [
976 ToggleButtonSimple::new("First", |_, _, _| {})
977 .tooltip(Tooltip::text("This is a tooltip. Hello!")),
978 ToggleButtonSimple::new("Second", |_, _, _| {})
979 .tooltip(Tooltip::text("This is a tooltip. Hey?")),
980 ToggleButtonSimple::new("Third", |_, _, _| {})
981 .tooltip(Tooltip::text("This is a tooltip. Get out of here now!")),
982 ],
983 )
984 .selected_index(1)
985 .into_any_element(),
986 )])
987 .into_any_element(),
988 )
989 }
990}