ButtonGroup
Groups multiple buttons together with connected borders and consistent sizing for cohesive action layouts.
Installation
npx vayu-ui-cli@latest add buttongroupUsage
Button Group Examples
Horizontal (Outline)
Default horizontal layout with outline variant buttons.
Primary
Grouped primary buttons for related actions.
Vertical
Stack buttons vertically using the orientation prop.
Full Width
Buttons stretch to fill the full container width.
Mixed Variants
Combine different button variants in a single group.
With Icons
Icon-only buttons grouped together as a toolbar.
Radius Variants
Control the border radius using design token scales.
Control
Surface
Overlay
Full
<ButtonGroup aria-label="Text alignment">
<Button variant="outline">
<Button.Text>Left</Button.Text>
</Button>
<Button variant="outline">
<Button.Text>Center</Button.Text>
</Button>
<Button variant="outline">
<Button.Text>Right</Button.Text>
</Button>
</ButtonGroup>
<ButtonGroup aria-label="Save options">
<Button variant="primary">
<Button.Text>Save</Button.Text>
</Button>
<Button variant="primary">
<Button.Text>Save & Close</Button.Text>
</Button>
</ButtonGroup>
<ButtonGroup orientation="vertical" aria-label="Vertical actions">
<Button variant="outline">
<Button.Text>Top</Button.Text>
</Button>
<Button variant="outline">
<Button.Text>Middle</Button.Text>
</Button>
<Button variant="outline">
<Button.Text>Bottom</Button.Text>
</Button>
</ButtonGroup>
<ButtonGroup fullWidth aria-label="Confirmation actions">
<Button variant="secondary">
<Button.Text>Cancel</Button.Text>
</Button>
<Button variant="primary">
<Button.Text>Confirm</Button.Text>
</Button>
</ButtonGroup>
<ButtonGroup aria-label="Mixed action buttons">
<Button variant="outline">
<Button.Text>Back</Button.Text>
</Button>
<Button variant="secondary">
<Button.Text>Save Draft</Button.Text>
</Button>
<Button variant="primary">
<Button.Text>Submit</Button.Text>
</Button>
</ButtonGroup>
<ButtonGroup radius="surface" aria-label="Formatted radius">
<Button variant="outline">
<Button.Text>A</Button.Text>
</Button>
<Button variant="outline">
<Button.Text>B</Button.Text>
</Button>
</ButtonGroup>
<ButtonGroup aria-label="Formatting options">
<Button variant="outline">
<Button.Icon>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/>
<path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/>
</svg>
</Button.Icon>
</Button>
<Button variant="outline">
<Button.Icon>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="19" x2="10" y1="4" y2="4"/>
<line x1="14" x2="15" y1="20" y2="4"/>
<line x1="5" x2="19" y1="20" y2="20"/>
</svg>
</Button.Icon>
</Button>
<Button variant="outline">
<Button.Icon>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M10 4h8a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4h-8"/>
<path d="M14 12H6"/>
<path d="M10 8l-4 4 4 4"/>
</svg>
</Button.Icon>
</Button>
</ButtonGroup>Anatomy
import { ButtonGroup, Button } from 'vayu-ui';
<ButtonGroup aria-label="Group label">
<Button variant="outline">
<Button.Text>Button 1</Button.Text>
</Button>
<Button variant="outline">
<Button.Text>Button 2</Button.Text>
</Button>
<Button variant="outline">
<Button.Text>Button 3</Button.Text>
</Button>
</ButtonGroup>;- ButtonGroup — Root container with
role="group". Manages orientation, sizing, radius, and focus stacking for child buttons via CSS. - Button — Individual action buttons rendered as children of the group. Supports all variants and subcomponents (
Button.Text,Button.Icon).
Accessibility
- Keyboard Support:
Tab— Move focus to the next focusable button.Shift + Tab— Move focus to the previous focusable button.Enter/Space— Activate the focused button.
- ARIA Attributes:
role="group"onButtonGroupindicates a related set of buttons.aria-labeloraria-labelledbyprovides the accessible group name. At least one is required.
- Focus Behavior:
- Focused and hovered buttons receive
z-10so the focus ring is fully visible over adjacent siblings (WCAG 2.4.11). - Focus follows natural DOM tab order through child buttons.
- Focused and hovered buttons receive
Screen reader behavior
When a screen reader encounters a ButtonGroup, it announces the group label (via aria-label or aria-labelledby) followed by the individual button labels in sequence. Each button is announced as a standard push button with its text content. Users navigate between buttons using Tab and Shift + Tab, and the screen reader announces each button as it receives focus. No additional state information is conveyed since button groups do not manage selection state.
Component Folder Structure
ButtonGroup/
├── ButtonGroup.tsx # Component with CSS-based sizing, radius, and focus management
├── types.ts # TypeScript type definitions (ButtonGroupProps, ButtonGroupRadius)
├── index.ts # Re-exports ButtonGroup and types
└── README.md # Component usage referenceProps
ButtonGroup
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | Stack direction of buttons. |
size | "small" | "medium" | "large" | "medium" | Size applied to all child buttons via CSS. |
radius | "control" | "surface" | "overlay" | "full" | "control" | Border radius variant using semantic design tokens. |
fullWidth | boolean | false | Stretch to fill container width. |
aria-label | string | — | Accessible label for the button group. |
aria-labelledby | string | — | ID of element that labels this group. |
className | string | — | Additional CSS classes. |
children | ReactNode | — | Button elements to group. |