ButtonGroup joins related actions into a single connected control. Use it when multiple buttons represent related choices or operations that belong together visually, like copy/cut/paste, or undo/redo.
Preview loads on approachPreview loads on approach
Exact source · button-group-showcase
// Copyright (c) Meta Platforms, Inc. and affiliates.
'use client';
import {ButtonGroup} from '@astryxdesign/core/ButtonGroup';
import {Button} from '@astryxdesign/core/Button';
import {IconButton} from '@astryxdesign/core/IconButton';
import {Stack} from '@astryxdesign/core/Layout';
import {Icon} from '@astryxdesign/core/Icon';
import {
ClipboardDocumentIcon,
ScissorsIcon,
ClipboardIcon,
ChevronDownIcon,
} from '@heroicons/react/24/outline';
export default function ButtonGroupShowcase() {
return (
<Stack direction="horizontal" gap={6} vAlign="center">
<ButtonGroup label="Clipboard actions">
<Button label="Copy" icon={<Icon icon={ClipboardDocumentIcon} />} />
<Button label="Cut" icon={<Icon icon={ScissorsIcon} />} />
<Button label="Paste" icon={<Icon icon={ClipboardIcon} />} />
</ButtonGroup>
<ButtonGroup label="Save options">
<Button label="Save" variant="primary" />
<IconButton
label="Save options"
variant="primary"
icon={<Icon icon={ChevronDownIcon} />}
/>
</ButtonGroup>
</Stack>
);
}
Usage
ButtonGroup joins related actions into a single connected control. Use it when multiple buttons represent related choices or operations that belong together visually, like copy/cut/paste, or undo/redo.
Group buttons that perform related actions on the same object, like copy, cut, paste on selected text.
Use the same variant for all buttons in a group so they look like a single connected unit.
Keep groups small (2–4 buttons). For more actions, use a Toolbar or DropdownMenu instead.
Don't mix wildly different actions. A Save button next to a Delete button in the same group is confusing.
Don't nest ButtonGroups. If you need multiple groups, place them side by side with a gap.
Name the group for what its buttons act on. The label is the group's accessible name and a screen reader reads it before each member.
Keep the group a single Tab stop. Arrow keys move between members along the orientation, Home/End jump to the ends, and disabled members are skipped. This is the WAI-ARIA APG roving tabindex technique: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex
Don't disable the group to show that an action is in flight. A disabled member drops focus, so a keyboard user loses their place; leave the group enabled and show progress on the button that started the work.
Default size for buttons in the group. Individual buttons can override.
isDisabled
boolean · default false
Whether all buttons in the group are disabled.
elevation
'none' | 'low' | 'med' | 'high' · default 'none'
Resting shadow depth for the whole group. The connected buttons share one surface, so the shadow lifts them as a unit. Use for a group that floats above content.
ref
React.Ref<HTMLDivElement>
Ref forwarded to the root element.
xstyle
StyleXStyles
StyleX styles for layout customization. Must be a stylex.create() value.
data-testid
string
Test selector for automated testing frameworks.
Anatomy
Button · required
One or more Button or IconButton children that form the connected group.
Divider · optional
A thin border between buttons, rendered automatically by the group.
Accessibility
Text label
Color contrast · 1.4.3 Contrast (Minimum) · 4.5:1
Text in each button must have at least 4.5:1 contrast with its background in every state. For Hover and Pointer down, measure the final background after the overlay is applied.
States: Rest, Hover, Pointer down
Essential icon or spinner arc
Color contrast · 1.4.11 Non-text Contrast · 3:1
An icon used instead of text must have at least 3:1 contrast with the button background. The moving spinner arc must also meet 3:1. An icon beside a visible label does not need its own check.
States: Icon only, Loading
Visible control boundary
Color contrast · 1.4.11 Non-text Contrast · 3:1 if needed
Some groups need a divider or edge to show each button. That divider or edge must have at least 3:1 contrast.
States: Rest
Keyboard focus indicator
Color contrast · 1.4.11 Non-text Contrast · 3:1
The focus outline must have at least 3:1 contrast with the area around it.
States: Focus visible
Disabled appearance
Color contrast · 1.4.3 and 1.4.11 exceptions · Not required
Disabled controls do not need to meet these contrast ratios.