ButtonGroup
Groups related segments in a bordered shell (`secondary` raised or `outline`) with inset, rounded segments separated by a small gap.
import { ButtonGroup, type ButtonGroupItem, type ButtonGroupVariant } from 'phoundry-ui'; Toggle group
Show code
<ButtonGroup
items={[
{ label: 'Day', active: view === 'day', onclick: () => (view = 'day') },
{ label: 'Week', active: view === 'week', onclick: () => (view = 'week') },
{ label: 'Month', active: view === 'month', onclick: () => (view = 'month') }
]}
/>Outline variant
Show code
<ButtonGroup
variant="outline"
items={[
{ label: 'Day', active: outlineView === 'day', onclick: () => (outlineView = 'day') },
{ label: 'Week', active: outlineView === 'week', onclick: () => (outlineView = 'week') },
{ label: 'Month', active: outlineView === 'month', onclick: () => (outlineView = 'month') }
]}
/>Small size
Show code
<ButtonGroup
size="sm"
items={[
{ label: 'List', active: listMode === 'list', onclick: () => (listMode = 'list') },
{ label: 'Grid', active: listMode === 'grid', onclick: () => (listMode = 'grid') }
]}
/>Disabled, loading, stable keys
Optional id on each item stabilizes reconciliation when the list reorders. Loading shows the same spinner glyph as other buttons.
Show code
<ButtonGroup
aria-label="Text alignment"
items={[
{ id: 'left', label: 'Left', active: align === 'left', onclick: () => (align = 'left') },
{ id: 'center', label: 'Center', disabled: true },
{ id: 'right', label: 'Right', loading: true, onclick: () => (align = 'right') },
]}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items required | ButtonGroupItem[] | — | Segment entries: `label` (required) plus `icon`, `iconOnly`, `active`, `disabled`, `loading`, `class`, `onclick`, and other native `<button>` attributes. |
| variant | 'secondary' | 'outline' | 'secondary' | `secondary` is the raised strip (default). `outline` matches `Button variant="outline"` shell styling (base fill, stronger outer border, radial highlight); the active segment is indicated by background only (`surface-overlay`). |
| size | 'sm' | 'md' | 'md' | Height of the group; maps to the same scale as `Button` sm/md content. |
| class | string | '' | Additional classes on the outer `role="group"` container. Width is intrinsic by default (`w-fit`, like `ButtonDropdown` split). Add `w-full` if the group should stretch in a layout. |
| ...rest | HTMLAttributes<HTMLDivElement> | — | Forwarded to the outer `role="group"` wrapper (`aria-label`, `data-*`, etc.). |
Usage tips
- Set
activeto reflect selection. Withvariant="secondary"(default), the active segment uses asurface-overlayfill. Withvariant="outline", styling aligns withButton variant="outline"for the shell; the active segment uses asurface-overlayfill only. - Icons, links, and the tooltip-based
titlepattern are not supported on group items; use a plainlabelstring for each segment.