Button group
A row or column of buttons that belong together — MAFO’s Organisation chart toolbar (Export full image · Export image · Compact · Expand all · Collapse all), the deck tool’s modal action row, the site’s cookie actions.
Beta · Actions · packages/css/src/components/button-group.css · React on Base UI: @pepperui/button-group
.pui-button-group · --connected · --vertical. Standard is space/8; connected shares edges. The primary, if any, is one and last.
Sizes across, states down.
What it is for
Section titled “What it is for”- Variant standard / connected × Orientation horizontal / vertical × Size small / medium / large (Button’s sizes; heights are Button’s)
- Five exposed Button - secondary instances — edit labels, states and icons on the instance, or swap any of them to Button or Button - ghost; Button 1 and Button end are always shown, Has button 3 / 4 / 5 add the middle ones (three by default), so the ends keep their corners and two is the minimum
- Connected = gap 0, inner corners 0 and inner stroke 0 on every button after the first — overrides on the instances, kept through Size and State swaps
- Connected is for outlined buttons; a row of filled (primary) buttons is a standard group — flush primaries have no seams
- Two to five buttons; the primary action, if any, is one and last (the deck tool’s modal row, Dialog’s footer)
Use when several actions belong to one object or one step — a toolbar over a chart, the actions of a form or dialog, export / view controls.
Do not use when the buttons are choices that stay pressed (Toggle group); they switch views (Tabs); it is one action with alternatives (Dropdown menu); the row needs text or a field between buttons (compose the pieces).
Relates to Button, Button - secondary, Button - ghost, Icon button, Toggle group, Dialog, Tabs list.
Anti-patterns two primaries in one group · a connected group of filled buttons · buttons of different sizes in one group · a row looped from Button with a hand-set gap instead of this component · more than five, which is a menu.
Keywords: button group, toolbar, actions, connected, segmented, action row, footer buttons
Figma — page Button group: Button group (12 variants)
shadcn: button-group
The markup — copy this
Section titled “The markup — copy this”The class, the parts, and nothing that is not in the package. The same block opens button-group.css.
<div class="pui-button-group" role="group"> <button class="pui-button pui-button--secondary">Export</button> …</div><div class="pui-button-group pui-button-group--connected pui-button-group--vertical" role="group">…</div>The modifiers
Section titled “The modifiers”| What it is | Note | |
|---|---|---|
| Variant | (none) standard · --connected | — |
| Orientation | (none) horizontal · --vertical | — |
Rules — two to five buttons, one size; the primary — if any — is one and last; connected is for outlined buttons (flush primaries have no seams).
Accessibility — measured, not assumed
Section titled “Accessibility — measured, not assumed”Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.
Contrast
Section titled “Contrast”| ink on ground | reads | floor | the matrix calls it | |
|---|---|---|---|---|
#ffffff on #e42521 |
4.57 | 4.5 | Danger button label (promised) | ok |
#544d4d on #ffffff |
8.24 | 4.5 | text.muted on surface.page (promised) | ok |
#0b0202 on #ffffff |
20.51 | 4.5 | text.default on surface.page (promised) | ok |
#ffffff on #0b0202 |
20.51 | 4.5 | Primary button label (promised) | ok |
4 distinct pair(s) rendered, 0 that axe calls a violation.
The focus ring
Section titled “The focus ring”16 of 16 focus stop(s) in this block meet WCAG 2.4.13 on screen — the same crop screenshotted focused and unfocused, and the difference measured.
Keyboard
Section titled “Keyboard”| role | tab stops | what the pattern requires | |
|---|---|---|---|
group .pui-button-group |
4 | — | — |
group .pui-button-group.pui-button-group--connected |
3 | — | — |
group .pui-button-group.pui-button-group--connected |
3 | — | — |
group .pui-button-group.pui-button-group--vertical |
3 | — | — |
group .pui-button-group.pui-button-group--vertical.pui-button-group--connected |
3 | — | — |
What the consumer’s script owes. role=“group” is a LABELLING role, not a composite: every button keeps its own tab stop and its own Enter / Space, which is what a person expects of adjacent buttons. Nothing to write.
Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).
Pepper UI v1.5.0
The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.