Skip to main content

Figma Storybook

Button Group

Displays two or more related buttons as a single, visually joined control. Use for segmented controls, pagination, and view toggles — never to group actions of different severity.

Figma Storybook Docs

Description

What it does

Groups two or more related buttons into a single, visually joined control — no gap between segments, flush edges.

Where it appears

Segmented controls (view-mode switches, status filters), pagination, toolbars, and export/format pickers — for example, the engagement list's view switcher or a table's pagination row.

Why it exists

Loose buttons placed near each other don't read as related. ButtonGroup collapses the gap so users see one control surface with multiple segments, not several unrelated actions.

Dependencies

Built directly on Web Awesome's <wa-button-group>, wrapping one or more Button instances. There is no separate Orbit wrapper component — it's the real wa-button-group element, styled with Orbit's theme.

Anatomy

PartRequired?Notes
Group container Required <wa-button-group> with a required label attribute — this is the group's accessible name (rendered as role="group" with aria-label). Set orientation="vertical" to stack segments instead of the horizontal default.
Button (resting) Required Every child is a Button with variant="neutral" and appearance="plain". Never brand, danger, success, or warning — button groups represent selection state, not action severity.
Button (active / selected) Optional The active segment — in a segmented control, pagination, or toggle pattern — uses appearance="filled" with the same variant="neutral": a solid neutral fill, never a brand colour.
Divider None There isn't one. Both plain and filled appearance have a fully transparent border in the real component — segments are separated only by the active segment's background fill, never by a visible border or line. Don't add a manual divider; it doesn't match what ships.

Variants

btngrp.equal

Equal-weight group

All segments equal weight — nothing selected.

Toolbar actions or format choices with no default — icon-only layout switches, export options.

btngrp.segmented

Segmented control

One segment filled to show the current selection, the rest plain.

Mutually exclusive filters or views — status filters, view-mode switches.

btngrp.pagination

Pagination

Current page filled; Previous/Next stay plain since they're navigation actions, not selections.

Paged tables and lists.

btngrp.toggle

Toggle group

Simulates a toggle by moving the filled state to whichever segment is active.

View switchers where exactly one option is always active (List / Grid / Map).

btngrp.vertical

Vertical

Same rules, stacked orientation.

Sidebars and narrow layouts where a horizontal group would wrap.

btngrp.split

With split action

A primary action joined to a menu trigger. Still variant="neutral" throughout — the group styling communicates 'joined', not 'important'.

A default action with secondary options behind a dropdown, visually anchored to it (e.g. Export ▾).

btngrp.sizes

Sizes

Every child in a group shares one size — xs/s/m/l/xl, matching Button's own scale.

Match the size of surrounding controls; don't mix sizes within a single group.

States

Grid
RESTING (UNSELECTED)
List
SELECTED / ACTIVE
State Behaviour
Resting (unselected) Transparent background, text-only, transparent border. Adjacent resting segments have no visible boundary between them at all — the label spacing and hover/focus states are the only cues.
Selected / active Solid neutral fill (--wa-color-neutral-fill-normal). Communicates the current selection without borrowing a brand colour.
Hover Resting segments pick up a subtle neutral fill on hover; the already-selected segment darkens slightly. Only one segment can be hovered at a time.
Focus Each button is its own tab stop with the standard focus ring — the group does not use roving tabindex.
Disabled Individual segments can be disabled independently (e.g. a Previous button on page one) while the rest of the group stays interactive.

Usage guidelines

When to use

  • Segmented controls — mutually exclusive view or filter switches (List / Map / Table).
  • Pagination controls.
  • Equal-weight action sets — export format choices, toolbar actions.

When not to use

  • Don't use for navigation between unrelated pages or sections — use tabs or a nav component instead.
  • Don't mix variants within a group. Every child stays variant="neutral"; if you need a colour-coded destructive action, pull it out as a standalone Button next to the group, not inside it.
  • Don't use more than four or five segments — beyond that, switch to a Select.

Do / Don't

Do

Keep every child variant="neutral", even the active segment — use appearance="filled" to show selection.

Don't

Use variant="brand" (or any non-neutral variant) on a button-group child to mark it 'selected' — this borrows the semantic action-severity colour. This was a real drift bug found and fixed across Orbit's own Storybook stories in August 2026 (Vertical, Toggle Group, Segmented Control, and With Split were all using variant="brand" on the active segment).

Do

Always set a descriptive label attribute on wa-button-group — it's the group's accessible name.

Don't

Leave the group unlabelled. Screen reader users then hear a sequence of buttons with no shared context.

Was this page helpful?

Updated 9 September 2026