GitHub
Core
Glass
Brutal
Humanist

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
Save
Share
Export
Delete
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 install @react-aria/focus
2

Copy and paste the following code into your project.

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/End keys jump to first/last enabled item

ButtonGroup Props

PropTypeDefaultDescription
itemsButtonGroupItemData[]Required. Array of button items.
size'default' | 'small''default'Button size variant.
activeIdstringCurrently active button ID.
onChange(id: string) => voidSelection change handler.
disabledbooleanfalseDisables all buttons in the group.
aria-labelstringAccessible label for the button group.
classNamestring''Additional CSS classes.

ButtonGroupItemData Props

PropTypeDefaultDescription
idstringRequired. Unique identifier for this item.
labelstringButton text. Omit for icon-only rendering.
leadingIconReactNodeIcon before the label.
trailingIconReactNodeIcon after the label (only when label is provided).
type'default' | 'error''default'Item styling. Use error for destructive actions.
disabledbooleanfalseDisables this specific item.

On this page