1use documented::Documented;
2use gpui::{
3 AnyElement, AnyView, ClickEvent, CursorStyle, DefiniteLength, FocusHandle, Hsla, MouseButton,
4 MouseClickEvent, MouseDownEvent, MouseUpEvent, Rems, StyleRefinement, relative,
5 transparent_black,
6};
7use smallvec::SmallVec;
8
9use crate::{DynamicSpacing, ElevationIndex, prelude::*};
10
11/// A trait for buttons that can be Selected. Enables setting the [`ButtonStyle`] of a button when it is selected.
12pub trait SelectableButton: Toggleable {
13 fn selected_style(self, style: ButtonStyle) -> Self;
14}
15
16/// A common set of traits all buttons must implement.
17pub trait ButtonCommon: Clickable + Disableable {
18 /// A unique element ID to identify the button.
19 fn id(&self) -> &ElementId;
20
21 /// The visual style of the button.
22 ///
23 /// Most commonly will be [`ButtonStyle::Subtle`], or [`ButtonStyle::Filled`]
24 /// for an emphasized button.
25 fn style(self, style: ButtonStyle) -> Self;
26
27 /// The size of the button.
28 ///
29 /// Most buttons will use the default size.
30 ///
31 /// [`ButtonSize`] can also be used to help build non-button elements
32 /// that are consistently sized with buttons.
33 fn size(self, size: ButtonSize) -> Self;
34
35 /// The tooltip that shows when a user hovers over the button.
36 ///
37 /// Nearly all interactable elements should have a tooltip. Some example
38 /// exceptions might a scroll bar, or a slider.
39 fn tooltip(self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self;
40
41 fn tab_index(self, tab_index: impl Into<isize>) -> Self;
42
43 fn layer(self, elevation: ElevationIndex) -> Self;
44
45 fn track_focus(self, focus_handle: &FocusHandle) -> Self;
46}
47
48#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
49pub enum IconPosition {
50 #[default]
51 Start,
52 End,
53}
54
55#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
56pub enum KeybindingPosition {
57 Start,
58 #[default]
59 End,
60}
61
62#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
63pub enum TintColor {
64 #[default]
65 Accent,
66 Error,
67 Warning,
68 Success,
69}
70
71impl TintColor {
72 fn button_like_style(self, cx: &mut App) -> ButtonLikeStyles {
73 match self {
74 TintColor::Accent => ButtonLikeStyles {
75 background: cx.theme().status().info_background,
76 border_color: cx.theme().status().info_border,
77 label_color: cx.theme().colors().text,
78 icon_color: cx.theme().colors().text,
79 },
80 TintColor::Error => ButtonLikeStyles {
81 background: cx.theme().status().error_background,
82 border_color: cx.theme().status().error_border,
83 label_color: cx.theme().colors().text,
84 icon_color: cx.theme().colors().text,
85 },
86 TintColor::Warning => ButtonLikeStyles {
87 background: cx.theme().status().warning_background,
88 border_color: cx.theme().status().warning_border,
89 label_color: cx.theme().colors().text,
90 icon_color: cx.theme().colors().text,
91 },
92 TintColor::Success => ButtonLikeStyles {
93 background: cx.theme().status().success_background,
94 border_color: cx.theme().status().success_border,
95 label_color: cx.theme().colors().text,
96 icon_color: cx.theme().colors().text,
97 },
98 }
99 }
100}
101
102impl From<TintColor> for Color {
103 fn from(tint: TintColor) -> Self {
104 match tint {
105 TintColor::Accent => Color::Accent,
106 TintColor::Error => Color::Error,
107 TintColor::Warning => Color::Warning,
108 TintColor::Success => Color::Success,
109 }
110 }
111}
112
113// Used to go from ButtonStyle -> Color through tint colors.
114impl From<ButtonStyle> for Color {
115 fn from(style: ButtonStyle) -> Self {
116 match style {
117 ButtonStyle::Tinted(tint) => tint.into(),
118 _ => Color::Default,
119 }
120 }
121}
122
123/// The visual appearance of a button.
124#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
125pub enum ButtonStyle {
126 /// A filled button with a solid background color. Provides emphasis versus
127 /// the more common subtle button.
128 Filled,
129
130 /// Used to emphasize a button in some way, like a selected state, or a semantic
131 /// coloring like an error or success button.
132 Tinted(TintColor),
133
134 /// Usually used as a secondary action that should have more emphasis than
135 /// a fully transparent button.
136 Outlined,
137
138 /// The default button style, used for most buttons. Has a transparent background,
139 /// but has a background color to indicate states like hover and active.
140 #[default]
141 Subtle,
142
143 /// Used for buttons that only change foreground color on hover and active states.
144 ///
145 /// TODO: Better docs for this.
146 Transparent,
147}
148
149#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
150pub(crate) enum ButtonLikeRounding {
151 All,
152 Left,
153 Right,
154}
155
156#[derive(Debug, Clone)]
157pub(crate) struct ButtonLikeStyles {
158 pub background: Hsla,
159 #[allow(unused)]
160 pub border_color: Hsla,
161 #[allow(unused)]
162 pub label_color: Hsla,
163 #[allow(unused)]
164 pub icon_color: Hsla,
165}
166
167fn element_bg_from_elevation(elevation: Option<ElevationIndex>, cx: &mut App) -> Hsla {
168 match elevation {
169 Some(ElevationIndex::Background) => cx.theme().colors().element_background,
170 Some(ElevationIndex::ElevatedSurface) => cx.theme().colors().elevated_surface_background,
171 Some(ElevationIndex::Surface) => cx.theme().colors().surface_background,
172 Some(ElevationIndex::ModalSurface) => cx.theme().colors().background,
173 _ => cx.theme().colors().element_background,
174 }
175}
176
177impl ButtonStyle {
178 pub(crate) fn enabled(
179 self,
180 elevation: Option<ElevationIndex>,
181
182 cx: &mut App,
183 ) -> ButtonLikeStyles {
184 match self {
185 ButtonStyle::Filled => ButtonLikeStyles {
186 background: element_bg_from_elevation(elevation, cx),
187 border_color: transparent_black(),
188 label_color: Color::Default.color(cx),
189 icon_color: Color::Default.color(cx),
190 },
191 ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
192 ButtonStyle::Outlined => ButtonLikeStyles {
193 background: element_bg_from_elevation(elevation, cx),
194 border_color: cx.theme().colors().border_variant,
195 label_color: Color::Default.color(cx),
196 icon_color: Color::Default.color(cx),
197 },
198 ButtonStyle::Subtle => ButtonLikeStyles {
199 background: cx.theme().colors().ghost_element_background,
200 border_color: transparent_black(),
201 label_color: Color::Default.color(cx),
202 icon_color: Color::Default.color(cx),
203 },
204 ButtonStyle::Transparent => ButtonLikeStyles {
205 background: transparent_black(),
206 border_color: transparent_black(),
207 label_color: Color::Default.color(cx),
208 icon_color: Color::Default.color(cx),
209 },
210 }
211 }
212
213 pub(crate) fn hovered(
214 self,
215 elevation: Option<ElevationIndex>,
216
217 cx: &mut App,
218 ) -> ButtonLikeStyles {
219 match self {
220 ButtonStyle::Filled => {
221 let mut filled_background = element_bg_from_elevation(elevation, cx);
222 filled_background.fade_out(0.5);
223
224 ButtonLikeStyles {
225 background: filled_background,
226 border_color: transparent_black(),
227 label_color: Color::Default.color(cx),
228 icon_color: Color::Default.color(cx),
229 }
230 }
231 ButtonStyle::Tinted(tint) => {
232 let mut styles = tint.button_like_style(cx);
233 let theme = cx.theme();
234 styles.background = theme.darken(styles.background, 0.05, 0.2);
235 styles
236 }
237 ButtonStyle::Outlined => ButtonLikeStyles {
238 background: cx.theme().colors().ghost_element_hover,
239 border_color: cx.theme().colors().border,
240 label_color: Color::Default.color(cx),
241 icon_color: Color::Default.color(cx),
242 },
243 ButtonStyle::Subtle => ButtonLikeStyles {
244 background: cx.theme().colors().ghost_element_hover,
245 border_color: transparent_black(),
246 label_color: Color::Default.color(cx),
247 icon_color: Color::Default.color(cx),
248 },
249 ButtonStyle::Transparent => ButtonLikeStyles {
250 background: transparent_black(),
251 border_color: transparent_black(),
252 // TODO: These are not great
253 label_color: Color::Muted.color(cx),
254 // TODO: These are not great
255 icon_color: Color::Muted.color(cx),
256 },
257 }
258 }
259
260 pub(crate) fn active(self, cx: &mut App) -> ButtonLikeStyles {
261 match self {
262 ButtonStyle::Filled => ButtonLikeStyles {
263 background: cx.theme().colors().element_active,
264 border_color: transparent_black(),
265 label_color: Color::Default.color(cx),
266 icon_color: Color::Default.color(cx),
267 },
268 ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
269 ButtonStyle::Subtle => ButtonLikeStyles {
270 background: cx.theme().colors().ghost_element_active,
271 border_color: transparent_black(),
272 label_color: Color::Default.color(cx),
273 icon_color: Color::Default.color(cx),
274 },
275 ButtonStyle::Outlined => ButtonLikeStyles {
276 background: cx.theme().colors().element_active,
277 border_color: cx.theme().colors().border_variant,
278 label_color: Color::Default.color(cx),
279 icon_color: Color::Default.color(cx),
280 },
281 ButtonStyle::Transparent => ButtonLikeStyles {
282 background: transparent_black(),
283 border_color: transparent_black(),
284 // TODO: These are not great
285 label_color: Color::Muted.color(cx),
286 // TODO: These are not great
287 icon_color: Color::Muted.color(cx),
288 },
289 }
290 }
291
292 #[allow(unused)]
293 pub(crate) fn focused(self, window: &mut Window, cx: &mut App) -> ButtonLikeStyles {
294 match self {
295 ButtonStyle::Filled => ButtonLikeStyles {
296 background: cx.theme().colors().element_background,
297 border_color: cx.theme().colors().border_focused,
298 label_color: Color::Default.color(cx),
299 icon_color: Color::Default.color(cx),
300 },
301 ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
302 ButtonStyle::Subtle => ButtonLikeStyles {
303 background: cx.theme().colors().ghost_element_background,
304 border_color: cx.theme().colors().border_focused,
305 label_color: Color::Default.color(cx),
306 icon_color: Color::Default.color(cx),
307 },
308 ButtonStyle::Outlined => ButtonLikeStyles {
309 background: cx.theme().colors().ghost_element_background,
310 border_color: cx.theme().colors().border,
311 label_color: Color::Default.color(cx),
312 icon_color: Color::Default.color(cx),
313 },
314 ButtonStyle::Transparent => ButtonLikeStyles {
315 background: transparent_black(),
316 border_color: cx.theme().colors().border_focused,
317 label_color: Color::Accent.color(cx),
318 icon_color: Color::Accent.color(cx),
319 },
320 }
321 }
322
323 #[allow(unused)]
324 pub(crate) fn disabled(
325 self,
326 elevation: Option<ElevationIndex>,
327 window: &mut Window,
328 cx: &mut App,
329 ) -> ButtonLikeStyles {
330 match self {
331 ButtonStyle::Filled => ButtonLikeStyles {
332 background: cx.theme().colors().element_disabled,
333 border_color: cx.theme().colors().border_disabled,
334 label_color: Color::Disabled.color(cx),
335 icon_color: Color::Disabled.color(cx),
336 },
337 ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
338 ButtonStyle::Subtle => ButtonLikeStyles {
339 background: cx.theme().colors().ghost_element_disabled,
340 border_color: cx.theme().colors().border_disabled,
341 label_color: Color::Disabled.color(cx),
342 icon_color: Color::Disabled.color(cx),
343 },
344 ButtonStyle::Outlined => ButtonLikeStyles {
345 background: cx.theme().colors().element_disabled,
346 border_color: cx.theme().colors().border_disabled,
347 label_color: Color::Default.color(cx),
348 icon_color: Color::Default.color(cx),
349 },
350 ButtonStyle::Transparent => ButtonLikeStyles {
351 background: transparent_black(),
352 border_color: transparent_black(),
353 label_color: Color::Disabled.color(cx),
354 icon_color: Color::Disabled.color(cx),
355 },
356 }
357 }
358}
359
360/// The height of a button.
361///
362/// Can also be used to size non-button elements to align with [`Button`]s.
363#[derive(Default, PartialEq, Clone, Copy)]
364pub enum ButtonSize {
365 Large,
366 Medium,
367 #[default]
368 Default,
369 Compact,
370 None,
371}
372
373impl ButtonSize {
374 pub fn rems(self) -> Rems {
375 match self {
376 ButtonSize::Large => rems_from_px(32.),
377 ButtonSize::Medium => rems_from_px(28.),
378 ButtonSize::Default => rems_from_px(22.),
379 ButtonSize::Compact => rems_from_px(18.),
380 ButtonSize::None => rems_from_px(16.),
381 }
382 }
383}
384
385/// A button-like element that can be used to create a custom button when
386/// prebuilt buttons are not sufficient. Use this sparingly, as it is
387/// unconstrained and may make the UI feel less consistent.
388///
389/// This is also used to build the prebuilt buttons.
390#[derive(IntoElement, Documented, RegisterComponent)]
391pub struct ButtonLike {
392 pub(super) base: Div,
393 id: ElementId,
394 pub(super) style: ButtonStyle,
395 pub(super) disabled: bool,
396 pub(super) selected: bool,
397 pub(super) selected_style: Option<ButtonStyle>,
398 pub(super) width: Option<DefiniteLength>,
399 pub(super) height: Option<DefiniteLength>,
400 pub(super) layer: Option<ElevationIndex>,
401 tab_index: Option<isize>,
402 size: ButtonSize,
403 rounding: Option<ButtonLikeRounding>,
404 tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
405 hoverable_tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
406 cursor_style: CursorStyle,
407 on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
408 on_right_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
409 children: SmallVec<[AnyElement; 2]>,
410 focus_handle: Option<FocusHandle>,
411}
412
413impl ButtonLike {
414 pub fn new(id: impl Into<ElementId>) -> Self {
415 Self {
416 base: div(),
417 id: id.into(),
418 style: ButtonStyle::default(),
419 disabled: false,
420 selected: false,
421 selected_style: None,
422 width: None,
423 height: None,
424 size: ButtonSize::Default,
425 rounding: Some(ButtonLikeRounding::All),
426 tooltip: None,
427 hoverable_tooltip: None,
428 children: SmallVec::new(),
429 cursor_style: CursorStyle::PointingHand,
430 on_click: None,
431 on_right_click: None,
432 layer: None,
433 tab_index: None,
434 focus_handle: None,
435 }
436 }
437
438 pub fn new_rounded_left(id: impl Into<ElementId>) -> Self {
439 Self::new(id).rounding(ButtonLikeRounding::Left)
440 }
441
442 pub fn new_rounded_right(id: impl Into<ElementId>) -> Self {
443 Self::new(id).rounding(ButtonLikeRounding::Right)
444 }
445
446 pub fn new_rounded_all(id: impl Into<ElementId>) -> Self {
447 Self::new(id).rounding(ButtonLikeRounding::All)
448 }
449
450 pub fn opacity(mut self, opacity: f32) -> Self {
451 self.base = self.base.opacity(opacity);
452 self
453 }
454
455 pub fn height(mut self, height: DefiniteLength) -> Self {
456 self.height = Some(height);
457 self
458 }
459
460 pub(crate) fn rounding(mut self, rounding: impl Into<Option<ButtonLikeRounding>>) -> Self {
461 self.rounding = rounding.into();
462 self
463 }
464
465 pub fn on_right_click(
466 mut self,
467 handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
468 ) -> Self {
469 self.on_right_click = Some(Box::new(handler));
470 self
471 }
472
473 pub fn hoverable_tooltip(
474 mut self,
475 tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
476 ) -> Self {
477 self.hoverable_tooltip = Some(Box::new(tooltip));
478 self
479 }
480}
481
482impl Disableable for ButtonLike {
483 fn disabled(mut self, disabled: bool) -> Self {
484 self.disabled = disabled;
485 self
486 }
487}
488
489impl Toggleable for ButtonLike {
490 fn toggle_state(mut self, selected: bool) -> Self {
491 self.selected = selected;
492 self
493 }
494}
495
496impl SelectableButton for ButtonLike {
497 fn selected_style(mut self, style: ButtonStyle) -> Self {
498 self.selected_style = Some(style);
499 self
500 }
501}
502
503impl Clickable for ButtonLike {
504 fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
505 self.on_click = Some(Box::new(handler));
506 self
507 }
508
509 fn cursor_style(mut self, cursor_style: CursorStyle) -> Self {
510 self.cursor_style = cursor_style;
511 self
512 }
513}
514
515impl FixedWidth for ButtonLike {
516 fn width(mut self, width: impl Into<DefiniteLength>) -> Self {
517 self.width = Some(width.into());
518 self
519 }
520
521 fn full_width(mut self) -> Self {
522 self.width = Some(relative(1.));
523 self
524 }
525}
526
527impl ButtonCommon for ButtonLike {
528 fn id(&self) -> &ElementId {
529 &self.id
530 }
531
532 fn style(mut self, style: ButtonStyle) -> Self {
533 self.style = style;
534 self
535 }
536
537 fn size(mut self, size: ButtonSize) -> Self {
538 self.size = size;
539 self
540 }
541
542 fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
543 self.tooltip = Some(Box::new(tooltip));
544 self
545 }
546
547 fn tab_index(mut self, tab_index: impl Into<isize>) -> Self {
548 self.tab_index = Some(tab_index.into());
549 self
550 }
551
552 fn layer(mut self, elevation: ElevationIndex) -> Self {
553 self.layer = Some(elevation);
554 self
555 }
556
557 fn track_focus(mut self, focus_handle: &gpui::FocusHandle) -> Self {
558 self.focus_handle = Some(focus_handle.clone());
559 self
560 }
561}
562
563impl VisibleOnHover for ButtonLike {
564 fn visible_on_hover(mut self, group_name: impl Into<SharedString>) -> Self {
565 self.base = self.base.visible_on_hover(group_name);
566 self
567 }
568}
569
570impl ParentElement for ButtonLike {
571 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
572 self.children.extend(elements)
573 }
574}
575
576impl RenderOnce for ButtonLike {
577 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
578 let style = self
579 .selected_style
580 .filter(|_| self.selected)
581 .unwrap_or(self.style);
582
583 self.base
584 .h_flex()
585 .id(self.id.clone())
586 .when_some(self.tab_index, |this, tab_index| this.tab_index(tab_index))
587 .when_some(self.focus_handle, |this, focus_handle| {
588 this.track_focus(&focus_handle)
589 })
590 .font_ui(cx)
591 .group("")
592 .flex_none()
593 .h(self.height.unwrap_or(self.size.rems().into()))
594 .when_some(self.width, |this, width| {
595 this.w(width).justify_center().text_center()
596 })
597 .when(matches!(self.style, ButtonStyle::Outlined), |this| {
598 this.border_1()
599 })
600 .when_some(self.rounding, |this, rounding| match rounding {
601 ButtonLikeRounding::All => this.rounded_sm(),
602 ButtonLikeRounding::Left => this.rounded_l_sm(),
603 ButtonLikeRounding::Right => this.rounded_r_sm(),
604 })
605 .gap(DynamicSpacing::Base04.rems(cx))
606 .map(|this| match self.size {
607 ButtonSize::Large | ButtonSize::Medium => this.px(DynamicSpacing::Base06.rems(cx)),
608 ButtonSize::Default | ButtonSize::Compact => {
609 this.px(DynamicSpacing::Base04.rems(cx))
610 }
611 ButtonSize::None => this.px_px(),
612 })
613 .border_color(style.enabled(self.layer, cx).border_color)
614 .bg(style.enabled(self.layer, cx).background)
615 .when(self.disabled, |this| {
616 if self.cursor_style == CursorStyle::PointingHand {
617 this.cursor_not_allowed()
618 } else {
619 this.cursor(self.cursor_style)
620 }
621 })
622 .when(!self.disabled, |this| {
623 let hovered_style = style.hovered(self.layer, cx);
624 let focus_color =
625 |refinement: StyleRefinement| refinement.bg(hovered_style.background);
626 this.cursor(self.cursor_style)
627 .hover(focus_color)
628 .map(|this| {
629 if matches!(self.style, ButtonStyle::Outlined) {
630 this.focus(|s| s.border_color(cx.theme().colors().border_focused))
631 } else {
632 this.focus(focus_color)
633 }
634 })
635 .active(|active| active.bg(style.active(cx).background))
636 })
637 .when_some(
638 self.on_right_click.filter(|_| !self.disabled),
639 |this, on_right_click| {
640 this.on_mouse_down(MouseButton::Right, |_event, window, cx| {
641 window.prevent_default();
642 cx.stop_propagation();
643 })
644 .on_mouse_up(
645 MouseButton::Right,
646 move |event, window, cx| {
647 cx.stop_propagation();
648 let click_event = ClickEvent::Mouse(MouseClickEvent {
649 down: MouseDownEvent {
650 button: MouseButton::Right,
651 position: event.position,
652 modifiers: event.modifiers,
653 click_count: 1,
654 first_mouse: false,
655 },
656 up: MouseUpEvent {
657 button: MouseButton::Right,
658 position: event.position,
659 modifiers: event.modifiers,
660 click_count: 1,
661 },
662 });
663 (on_right_click)(&click_event, window, cx)
664 },
665 )
666 },
667 )
668 .when_some(
669 self.on_click.filter(|_| !self.disabled),
670 |this, on_click| {
671 this.on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
672 .on_click(move |event, window, cx| {
673 cx.stop_propagation();
674 (on_click)(event, window, cx)
675 })
676 },
677 )
678 .when_some(self.tooltip, |this, tooltip| {
679 this.tooltip(move |window, cx| tooltip(window, cx))
680 })
681 .when_some(self.hoverable_tooltip, |this, tooltip| {
682 this.hoverable_tooltip(move |window, cx| tooltip(window, cx))
683 })
684 .children(self.children)
685 }
686}
687
688impl Component for ButtonLike {
689 fn scope() -> ComponentScope {
690 ComponentScope::Input
691 }
692
693 fn sort_name() -> &'static str {
694 // ButtonLike should be at the bottom of the button list
695 "ButtonZ"
696 }
697
698 fn description() -> Option<&'static str> {
699 Some(ButtonLike::DOCS)
700 }
701
702 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
703 Some(
704 v_flex()
705 .gap_6()
706 .children(vec![
707 example_group(vec![
708 single_example(
709 "Default",
710 ButtonLike::new("default")
711 .child(Label::new("Default"))
712 .into_any_element(),
713 ),
714 single_example(
715 "Filled",
716 ButtonLike::new("filled")
717 .style(ButtonStyle::Filled)
718 .child(Label::new("Filled"))
719 .into_any_element(),
720 ),
721 single_example(
722 "Subtle",
723 ButtonLike::new("outline")
724 .style(ButtonStyle::Subtle)
725 .child(Label::new("Subtle"))
726 .into_any_element(),
727 ),
728 single_example(
729 "Tinted",
730 ButtonLike::new("tinted_accent_style")
731 .style(ButtonStyle::Tinted(TintColor::Accent))
732 .child(Label::new("Accent"))
733 .into_any_element(),
734 ),
735 single_example(
736 "Transparent",
737 ButtonLike::new("transparent")
738 .style(ButtonStyle::Transparent)
739 .child(Label::new("Transparent"))
740 .into_any_element(),
741 ),
742 ]),
743 example_group_with_title(
744 "Button Group Constructors",
745 vec![
746 single_example(
747 "Left Rounded",
748 ButtonLike::new_rounded_left("left_rounded")
749 .child(Label::new("Left Rounded"))
750 .style(ButtonStyle::Filled)
751 .into_any_element(),
752 ),
753 single_example(
754 "Right Rounded",
755 ButtonLike::new_rounded_right("right_rounded")
756 .child(Label::new("Right Rounded"))
757 .style(ButtonStyle::Filled)
758 .into_any_element(),
759 ),
760 single_example(
761 "Button Group",
762 h_flex()
763 .gap_px()
764 .child(
765 ButtonLike::new_rounded_left("bg_left")
766 .child(Label::new("Left"))
767 .style(ButtonStyle::Filled),
768 )
769 .child(
770 ButtonLike::new_rounded_right("bg_right")
771 .child(Label::new("Right"))
772 .style(ButtonStyle::Filled),
773 )
774 .into_any_element(),
775 ),
776 ],
777 ),
778 ])
779 .into_any_element(),
780 )
781 }
782}