Buttons

Button Group

Group related buttons with a shared variant and merged edges.

Rust
1use herogpui::components::button_group::ButtonGroup;

Usage

Rust
1use herogpui::prelude::{ActiveTheme, Button, ButtonGroup, icons};
2use gpui::prelude::*;
3use gpui::px;
4
5ButtonGroup::new()
6    .separators(true)
7    .button(Button::new("button-group-1").label("Merge pull request"))
8    .button(
9        Button::new("button-group-2")
10            .is_icon_only(true)
11            .child(gpui::svg()
12                       .size(px(16.))
13                       .path(icons::CHEVRON_DOWN)
14                       .text_color(cx.colors().foreground)),
15    )

Live HeroGPUI compiled to WebAssembly. Select any example without loading another WASM instance.

Anatomy

Rust types

ButtonGroup

Button Group is assembled from these builders. The API reference lists each one.

Customization

Appearance builders and theme tokens Button Group uses.

Styling

Button Group styling
StyleDescription
div flex items_center justify_centerFlex alignment and zero gap match; GPUI has no inline-flex display mode and relies on the parent layout for intrinsic width.
Orientation + flex_row/flex_colBoth orientations match.
GroupEdge + group_radiusOnly the first/last external corners retain the 24px Button radius, and a lone member keeps the full radius.
group_edge.is_none() gateGrouped members skip Button's pressed-scale wrapper.
ring_if_focusedThe outward focus ring renders, but GPUI provides no matching local z-index elevation.
separators + separator_variant + absolute hairlineHorizontal and vertical separator geometry and opacity match; bg-current resolves per member, so each hairline takes the resolved variant foreground of the member drawn in its slot and a type-erased child's slot falls back to the group variant. The inert opacity transition has no runtime-changing endpoint in this composition.
Button outline + collapsed_border_sides(GroupEdge, vertical)Each outline member drops exactly the border sides its group position shares with a neighbour, resolved per GroupEdge and orientation; a lone member is:first-child:last-child so its whole stacking-axis border collapses, and a member outside a group keeps the full border.
full_width + Button::group_defaults + per-member flex_1The group root and each resolved-full member stretch; an explicit child fullWidth=false overrides the context and hugs content, matching pinned button.tsx precedence.

API reference

Builders

Button Group builders
BuilderTypeDefaultDescription
variant(Variant) + Button::group_defaults'primary' | 'secondary' | 'tertiary' | 'outline' | 'ghost' | 'danger' | 'danger-soft'Supplies a default variant to direct Button members while preserving explicit child variants; unset members keep Button's own default. The pinned context type is ButtonProps['variant'], so all seven values inherit.
size(Size) + Button::group_defaults'sm' | 'md' | 'lg'Supplies a default size to direct Button members while preserving explicit child sizes; unset members keep Button's own default.
orientation(Orientation)OrientationOrientation::HorizontalChooses row or column layout and the corresponding joined-edge geometry.
full_width(bool) + Button::group_defaultsboolfalseThe group root fills its parent, and each typed member resolves pinned button.tsx's finalFullWidth = fullWidth ?? Context.fullWidth: unset members inherit, an explicit child false/true overrides, and only resolved-full members take an equal stretch slot.
is_disabled(bool) + Button::group_defaultsboolfalseDisables direct typed members unless a child explicitly sets isDisabled=false, matching pinned context precedence.
button(Button) / child(AnyElement)Button / AnyElementButton(Button) preserves typed direct-child inheritance and joined edges; arbitrary ParentElement children are rendered but cannot receive that context after type erasure, so they take no fullWidth stretch slot either.
separators(bool)boolSynthesizes pinned separators through a composition flag rather than accepting browser classes.

Parts

Button Group parts
PartDescription
ButtonGroupOrientation, width, direct-child defaults, and joined-edge owner.
ButtonGroupOptional hairline drawn by ButtonGroup::separators(bool) before each member after the first; composes one child per member, so per-member placement is not expressible.

States

Button Group states
BuilderStateDescription
Orientation::Horizontal + GroupEdgeHorizontalMembers form a row with start/end outer corners.
Orientation::Vertical + GroupEdgeVerticalMembers form a column with top/bottom outer corners.
full_width + w_full + resolved member flex_1 slotsFull widthThe group fills its parent; each member that resolves fullWidth ?? Context.fullWidth shares the width equally, and an explicit child false frees its share.
Button::group_defaults precedenceDisabledUnset children inherit disabled; an explicit child false overrides it.
Button group_edge skips anim::pressedPressedGrouped buttons suppress the standalone press scale.
Button ring_if_focused without z-10Focus visibleThe focus ring is present, but GPUI has no z-index elevation equivalent for overlapping adjacent controls.