Button Group
ButtonGroup provides a way to group related buttons together, supporting selection states, icons, and consistent layout.
Button Group Playground
Button Group Playground
Preview
Code
Controls
Size:
Default
Small
Show Icon:
Show Text:
Disabled:
Installation
You can add the button group component to your project manually:
1
Install the following dependencies:
npm
pnpm
yarn
bun
npm install @react-aria/focus2
Copy and paste the following code into your project.
ButtonGroup.tsx
ButtonGroupItem.tsx
Loading source code...
3
Update the import paths to match your project setup.
Update the import aliases (e.g. @/components, @/utils) in the copied files to match your project's path configuration.
Basic Usage
A simple button group with text labels:
import { ButtonGroup } from '@versaui/ui/components/ButtonGroup';
<ButtonGroup
items={[
{ id: 'left', label: 'Left' },
{ id: 'center', label: 'Center' },
{ id: 'right', label: 'Right' },
]}
activeId="center"
onChange={(id) => setAlignment(id)}
/>With Icons
Add leading icons to button items. When label is omitted, the button renders as icon-only:
import { FloppyDiskIcon, ShareNetworkIcon, TrashIcon } from '@phosphor-icons/react';
// Icons with text
<ButtonGroup
items={[
{ id: 'save', label: 'Save', leadingIcon: <FloppyDiskIcon /> },
{ id: 'share', label: 'Share', leadingIcon: <ShareNetworkIcon /> },
{ id: 'delete', label: 'Delete', leadingIcon: <TrashIcon />, type: 'error' },
]}
activeId="save"
onChange={setActive}
/>
// Icon-only (omit label)
<ButtonGroup
items={[
{ id: 'save', leadingIcon: <FloppyDiskIcon /> },
{ id: 'share', leadingIcon: <ShareNetworkIcon /> },
{ id: 'delete', leadingIcon: <TrashIcon />, type: 'error' },
]}
activeId="save"
onChange={setActive}
/>Size Variants
Two sizes available — default and small:
<ButtonGroup size="default" items={items} activeId={id} onChange={setId} />
<ButtonGroup size="small" items={items} activeId={id} onChange={setId} />Error Type
Individual items can use type: 'error' for destructive actions:
<ButtonGroup
items={[
{ id: 'save', label: 'Save' },
{ id: 'delete', label: 'Delete', type: 'error' },
]}
activeId="save"
onChange={setActive}
/>Disabled State
Disable the entire group or individual items:
// Entire group disabled
<ButtonGroup disabled items={items} activeId={id} onChange={setId} />
// Individual item disabled
<ButtonGroup
items={[
{ id: 'save', label: 'Save' },
{ id: 'share', label: 'Share', disabled: true },
{ id: 'delete', label: 'Delete' },
]}
activeId="save"
onChange={setActive}
/>Accessibility
- Uses
role="group"with proper labeling - Keyboard navigation between buttons with arrow keys
- Active button announced via
aria-pressed Home/Endkeys jump to first/last enabled item
ButtonGroup Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | ButtonGroupItemData[] | — | Required. Array of button items. |
size | 'default' | 'small' | 'default' | Button size variant. |
activeId | string | — | Currently active button ID. |
onChange | (id: string) => void | — | Selection change handler. |
disabled | boolean | false | Disables all buttons in the group. |
aria-label | string | — | Accessible label for the button group. |
className | string | '' | Additional CSS classes. |
ButtonGroupItemData Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | Required. Unique identifier for this item. |
label | string | — | Button text. Omit for icon-only rendering. |
leadingIcon | ReactNode | — | Icon before the label. |
trailingIcon | ReactNode | — | Icon after the label (only when label is provided). |
type | 'default' | 'error' | 'default' | Item styling. Use error for destructive actions. |
disabled | boolean | false | Disables this specific item. |