A button group is a row of joined System buttons for choosing between two to four short options. The selected button has a black 12% fill.
Tokens, sizes, measurements, states and requirements. Values come from the live token package and from the specification skill: no Figma component is linked.
Resolved from the live token package.
| State | Part | Token | Value |
|---|
| Breakpoint | Height | Padding | Label |
|---|---|---|---|
| Mobile and tablet | 32px | 0 10px | 14/14, 0.42px, uppercase, weight 600 |
| Desktop (769px+) | 40px | 0 16px | 16/16, 0.48px, uppercase, weight 600 |
The tablet range (640 to 768px) uses the mobile values. The 1px frame is drawn inside each button (inset box-shadow) and shared between neighbours with margin-left: -1px. The group is inline-flex and never wider than its parent.
The padding of one button, left and right. The numbers are read from the component.
| Attribute | Mobile and tablet | Desktop (769px+) |
|---|---|---|
| Height | 32px | 40px |
| Padding left and right | 10px | 16px |
| Padding above and below | None: the height is fixed and the content is centred | None |
| Frame | 1px, inside the box, shared with the neighbour (margin-left: -1px) | The same |
| Focus ring | 2px line, 2px gap, outside the box | The same |
The side padding as a spacing token.
| Part | Value |
|---|---|
| Padding, desktop | space-16 |
| Padding, mobile | 10px: literal, no spacing token |
Selected is a black 12% fill (aria-pressed="true"). Hover darkens the frame and, when not selected, adds the fill. Hover and focus are forced on this page; in your code they come from :hover and the keyboard focus rule.
| State | Not selected | Selected |
|---|
| Part | Type | Mobile and tablet | Desktop (769px+) |
|---|---|---|---|
| Label | label-md | 14/14, 0.42px | 16/16, 0.48px |
Breuer Condensed, weight 600, uppercase through CSS, so write the label in sentence case in the HTML. No font features, as for the Small button.
| Element | Class | Notes |
|---|---|---|
| Group | btn-group | role="group" with aria-label or aria-labelledby. inline-flex, max-width: 100%. |
| Button | button inside the group | A real <button type="button">. Selected is aria-pressed="true". |
The group is as wide as its buttons and never wider than its parent. It never wraps. Two to four options.
| Property | Duration | Easing |
|---|---|---|
Fill: opacity of ::before | duration-fast-2 (100ms) | ease-standard |
Frame: box-shadow | duration-fast-2 | ease-standard |
Focus ring: outline-color | duration-fast-2 | ease-standard |
The same dissolve as the Button. Under prefers-reduced-motion: reduce the transition is turned off.
| Topic | Rule |
|---|---|
| Selection | One selected at a time, set by your script via aria-pressed. The CSS does not toggle it. |
| Markup | role="group" with aria-label or aria-labelledby; real <button type="button">. |
| Tab | Each button is focusable; 2px focus ring with a 2px gap on keyboard focus. |
| Not navigation | A System button group toggles state. Page navigation uses links. |
| Count | Two to four options. More: a select. When the group is wider than its container, show a select with the same options and keep the two in sync; never shrink, wrap or scroll the group. |
| Topic | Requirement |
|---|---|
| Markup | role="group" with an accessible name; real buttons with aria-pressed. |
| Focus | 2px ring border-focus with a 2px gap, on keyboard use (WCAG 2.4.7, 1.4.11). It is set with body.keyboard-nav. |
| State | The selected button differs by its fill and by aria-pressed, not by color alone (WCAG 1.4.1). |
| Disabled | Not focusable. Disabled tokens are exempt from contrast requirements. |