You're in the Library

ButtonGroup

Lays out related buttons as one unit, either spaced (an action bar or dialog footer) or attached (a segmented control), and gives the group one accessible name.
Stable
Edit

Preview appears after the next Storybook update.

ButtonGroup example
<ButtonGroup />
Rendered with the real componentFrom the code
Light
Dark

When to use

Use it for

  • Footers of dialogs, forms and cards: primary at the end, alternatives before it.
  • Attached: two to five closely related choices of equal weight, like Unified or Split diff.

Not for

  • Switching between views of content: use Tabs, which manage the panel and arrow-key navigation.
  • A single choice that persists as a setting: use RadioGroup.

Do and don't

Every example is rendered with the real component, so it always matches what ships.

Do

Put the primary action last

Users read the alternatives on the way to the main action, and the primary lands where the eye ends.

Don't

Mix variants in an attached group

An attached group reads as one control. Mixed fills break it into unrelated pieces.

Accessibility

  • Renders role="group". Pass aria-label when the buttons are related choices so the group is announced.
  • Each button stays in the tab order; the focused button lifts above its neighbors so the ring is never clipped.
  • Vertical groups stack the same buttons; the tab order follows the visual order.

Content guidelines

  • Labels in one group share a grammatical form: all verbs, or all nouns for view choices.
  • Keep attached groups to five items or fewer.

From the code Generated from the component, not editable here.

Anatomy and tokens

Read from packages/react/src/components/ButtonGroup/ButtonGroup.module.css at build time. Every value is a token: open one to see its alias chain in both themes.

2 tokens1 semantic or component, change with theme and brand1 from the shared scales

Motion and interaction

ButtonGroup does not animate: it only lays out other components.

From the code Generated from the component, not editable here.

Props

Parsed from the TypeScript types in packages/react/src/components/ButtonGroup/ButtonGroup.tsx, so this table cannot drift from the code. It also accepts every native <div> attribute.

PropTypeDefaultDescription
appearance'spaced' | 'attached''spaced'Accessible name for the group, for example "Text alignment". Required when the buttons are related choices. */ 'aria-label'?: string; /** `attached` joins the buttons into one segmented control; `spaced` keeps a gap (action bars). Default `spaced`.
orientation'horizontal' | 'vertical''horizontal'No description in the code yet.
align'start' | 'end' | 'between''start'Align the group's buttons. Default `start`. Use `end` for dialog and form footers.

Playground

Change the props and see the real ButtonGroup update. Controls are generated from the TypeScript props; nothing here changes the system.

Code for these props
<ButtonGroup align="end" aria-label="Review actions" />

appearance

orientation

align

Workbench

For contributors: every state with the accessibility panel, in the component workbench (Storybook). The stories double as visual test fixtures; the guidance on this page is the user documentation (open ButtonGroup in Storybook).

Embed Storybook stories here (3)

Loads from https://bridge-storybook.floriangouloubi.com (set STORYBOOK_URL at build time). If Storybook is not running, the frames stay empty.

Footer

Attached

AllStates

From the code Generated from the component, not editable here.

Changelog

  • Fix

    ButtonGroup: the focus rule of attached groups uses > :focus-visible, same behaviour, no universal selector

    v1.0.0, Nov 11, 2026

All release notes