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