The ButtonGroup component renders a group of related buttons next to each other.

ButtonGroup

Usage

  • Use ButtonGroup to wrap two or more Buttons that form a unified set of related actions, and to share variant, size, and isDisabled across them.
  • Use Tabs instead when the buttons switch between panels of content — ButtonGroup and Tabs are not interchangeable.
  • Use the segmented group for closely-related actions in a single context: zoom controls, a WYSIWYG toolbar, forward and back.
  • Use the spaced group for form submission and cancellation, and for actions in a modal footer.
  • Keep props consistent across the Buttons in a group — never mix sizes or variants on individual Buttons.
  • Limit a group to four Buttons. Move extra actions into a DropdownMenu or pair the main action with one in a split button.
  • Allow more visible Buttons in an icon-only toolbar before moving the rest into a DropdownMenu.
  • Order actions from least to most important, left to right, with the confirming action last.
  • Limit one primary Button per workflow or page.
  • Build the icon toolbar configuration as a segmented group of icon-only Buttons for actions on a canvas or preview; give each an aria-label.
  • Build the paired-actions configuration — the most common one — as a spaced group of a cancel action and a confirming action.
  • Build pagination controls as a segmented group of icon-only navigation Buttons.
  • Build a split button as a segmented group of one Button plus a DropdownMenu whose trigger is a DropdownMenuTriggerButton.

Variants

  • groupVariant="segmented" (default) — Buttons connect into a single control with overlapping borders.
  • groupVariant="spaced" — Buttons keep their default styling with space-100 between them.

Appearance

  • size="md" — the default; use in the majority of cases.
  • size="sm" — for smaller screens and less prominent actions.
  • Use icons consistently — if one Button in the group has an icon, all of them must.
  • Use icon-only Buttons (isIconOnly) for toolbars, and only for commonly-understood icons.
  • Pair icons with labels for less-common icons or to communicate the action more clearly.

Behaviors

  • Hover, focus (a 2px outline), and active states are built into the Buttons — no group prop controls them.
  • Disabled (isDisabled) — set on the group, disables every Button in it and lightens the colors.
  • Variant inheritance — a Button with its own variant keeps it; a Button with none adopts the group's.
  • Size inheritance — the group's size always overrides each Button's own, keeping visual hierarchy consistent.
  • Disabled inheritance — a Button set isDisabled individually stays disabled even when the group is enabled.

Content

  • Write every label in the group by the Button content rules — see the Button component's guidelines.

Implementation Notes

  • Content — React passes the Buttons as children. Ember yields the default block: <PlumaButtonGroup>...</PlumaButtonGroup>.
  • The group shares its settings through React context / an Ember context provider, so variant, size, isDisabled, unsafe_iconColor, and unsafe_iconSize reach any descendant Button, not only direct children.
  • Segmented border and z-index styling applies only to direct children carrying the Button class. Wrapping a Button in another element breaks the connected appearance; DropdownMenuTriggerButton renders a Button and works as a direct child.
  • variant accepts the Button values primary, secondary (default), tertiary, and subtle. The design docs' "Tertiary" is variant="subtle" — a literal tertiary also exists with different styling, so do not substitute it.
  • size accepts md (default) and sm. medium and small are deprecated aliases — use md and sm.
  • unsafe_iconColor / unsafe_iconSize — override icon color and size for every Button in the group. Use deliberately; they cause UI inconsistency.
  • The spaced gap is overridable through the buttonGroupSpacedGap CSS variable exported from button-group.style-exports.ts; it defaults to space-100.
  • Extends Box — sprinkle props (spacing, layout, flexWrap) are supported, and as changes the element from the default div.
  • Ember invocation: <PlumaButtonGroup @groupVariant="spaced" @variant="tertiary" @size="sm">.

On this page