button_like.rs

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