button_group: Add vertical (#1537)

Adds a vertical option to the button group

Also added an example of the vertical button group to the story

Also fixed button rounding only working when both tl/bl and tr/br are
both set, now they can be set individually

I'm not sure if the justify_center in `.when(self.vertical, |this|
this.flex_col().justify_center())` is needed, but I added it to match
the behaviour of `.items_center()` when the flex direction is row.
This commit is contained in:
Moulberry 2025-11-07 16:48:14 +08:00 committed by GitHub
parent 001107438f
commit c78811c4b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 66 additions and 31 deletions

View file

@ -1,5 +1,5 @@
use gpui::{
Action, App, AppContext as _, ClickEvent, Context, Corner, Entity, Focusable,
Action, App, AppContext as _, Axis, ClickEvent, Context, Corner, Entity, Focusable,
InteractiveElement, IntoElement, ParentElement as _, Render, Styled as _, Window,
prelude::FluentBuilder, px,
};
@ -612,6 +612,38 @@ impl Render for ButtonStory {
),
),
)
.child(
section("Button Group (Vertical)").child(
ButtonGroup::new("button-group-vertical")
.outline()
.layout(Axis::Vertical)
.disabled(disabled)
.child(
Button::new("button-one")
.label("One")
.disabled(disabled)
.selected(selected)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-two")
.label("Two")
.disabled(disabled)
.selected(selected)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-three")
.label("Three")
.disabled(disabled)
.selected(selected)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
),
),
)
.child(
section("Toggle Button Group")
.sub_title(

View file

@ -430,6 +430,14 @@ impl RenderOnce for Button {
.clone();
let is_focused = focus_handle.is_focused(window);
let rounding = match self.rounded {
ButtonRounded::Small => cx.theme().radius * 0.5,
ButtonRounded::Medium => cx.theme().radius,
ButtonRounded::Large => cx.theme().radius * 2.0,
ButtonRounded::Size(px) => px,
ButtonRounded::None => Pixels::ZERO,
};
self.base
.when(!self.disabled, |this| {
this.track_focus(
@ -467,26 +475,10 @@ impl RenderOnce for Button {
}
}
})
.when(
self.border_corners.top_left && self.border_corners.bottom_left,
|this| match self.rounded {
ButtonRounded::Small => this.rounded_l(cx.theme().radius * 0.5),
ButtonRounded::Medium => this.rounded_l(cx.theme().radius),
ButtonRounded::Large => this.rounded_l(cx.theme().radius * 2.0),
ButtonRounded::Size(px) => this.rounded_l(px),
ButtonRounded::None => this.rounded_none(),
},
)
.when(
self.border_corners.top_right && self.border_corners.bottom_right,
|this| match self.rounded {
ButtonRounded::Small => this.rounded_r(cx.theme().radius * 0.5),
ButtonRounded::Medium => this.rounded_r(cx.theme().radius),
ButtonRounded::Large => this.rounded_r(cx.theme().radius * 2.0),
ButtonRounded::Size(px) => this.rounded_r(px),
ButtonRounded::None => this.rounded_none(),
},
)
.when(self.border_corners.top_left, |this| this.rounded_tl(rounding))
.when(self.border_corners.top_right, |this| this.rounded_tr(rounding))
.when(self.border_corners.bottom_left, |this| this.rounded_bl(rounding))
.when(self.border_corners.bottom_right, |this| this.rounded_br(rounding))
.when(self.border_edges.left, |this| this.border_l_1())
.when(self.border_edges.right, |this| this.border_r_1())
.when(self.border_edges.top, |this| this.border_t_1())

View file

@ -1,5 +1,5 @@
use gpui::{
div, prelude::FluentBuilder as _, App, Corners, Edges, ElementId, InteractiveElement,
div, prelude::FluentBuilder as _, App, Axis, Corners, Edges, ElementId, InteractiveElement,
IntoElement, ParentElement, RenderOnce, StatefulInteractiveElement as _, StyleRefinement,
Styled, Window,
};
@ -18,6 +18,7 @@ pub struct ButtonGroup {
children: Vec<Button>,
pub(super) multiple: bool,
pub(super) disabled: bool,
pub(super) layout: Axis,
// The button props
pub(super) compact: bool,
@ -48,6 +49,7 @@ impl ButtonGroup {
outline: false,
multiple: false,
disabled: false,
layout: Axis::Horizontal,
on_click: None,
}
}
@ -70,6 +72,12 @@ impl ButtonGroup {
self
}
/// Set the layout of the button group. Default is `Axis::Horizontal`.
pub fn layout(mut self, layout: Axis) -> Self {
self.layout = layout;
self
}
/// With the compact mode for the ButtonGroup.
///
/// See also: [`Button::compact()`]
@ -150,10 +158,13 @@ impl RenderOnce for ButtonGroup {
}
}
let vertical = self.layout == Axis::Vertical;
div()
.id(self.id)
.flex()
.items_center()
.when(vertical, |this| this.flex_col().justify_center())
.when(!vertical, |this| this.items_center())
.refine_style(&self.style)
.children(
self.children
@ -168,8 +179,8 @@ impl RenderOnce for ButtonGroup {
child
.border_corners(Corners {
top_left: true,
top_right: false,
bottom_left: true,
top_right: vertical,
bottom_left: !vertical,
bottom_right: false,
})
.border_edges(Edges {
@ -182,15 +193,15 @@ impl RenderOnce for ButtonGroup {
// Last
child
.border_edges(Edges {
left: false,
top: true,
left: vertical,
top: !vertical,
right: true,
bottom: true,
})
.border_corners(Corners {
top_left: false,
top_right: true,
bottom_left: false,
top_right: !vertical,
bottom_left: vertical,
bottom_right: true,
})
} else {
@ -198,8 +209,8 @@ impl RenderOnce for ButtonGroup {
child
.border_corners(Corners::all(false))
.border_edges(Edges {
left: false,
top: true,
left: vertical,
top: !vertical,
right: true,
bottom: true,
})