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