Connected segments are ideal for related actions (Back / Next / Save) and split actions.
import { ButtonGroup } from "@/design-system/components/ButtonGroup";
import { Button } from "@/design-system/components/Button";
export function Example() {
return (
<ButtonGroup segmented variant="primary" size="sm" aria-label="Wizard actions">
<Button>Back</Button>
<Button>Next</Button>
<Button>Save</Button>
</ButtonGroup>
);
}
import { ChevronDown } from "lucide-react";
<ButtonGroup segmented variant="primary" size="sm" aria-label="Split action">
<Button>New note</Button>
<Button iconOnly aria-label="More options">
<ChevronDown size={16} />
</Button>
</ButtonGroup>Innovative enterprise style: a true segmented-control surface with a moving pill indicator for high scanability.
import { useState } from "react";
import { ButtonGroup } from "@/design-system/components/ButtonGroup";
import { Button } from "@/design-system/components/Button";
export function Example() {
const [view, setView] = useState<"grid" | "list">("grid");
return (
<ButtonGroup
toggle
segmented
segmentedStyle="control"
indicator
tone="primary"
size="sm"
value={view}
onChange={(v) => setView(v as any)}
aria-label="View mode"
>
<Button itemValue="grid" leadingIcon={<LayoutGrid size={16} />}>Grid</Button>
<Button itemValue="list" leadingIcon={<List size={16} />}>List</Button>
</ButtonGroup>
);
}
Single-select toggle controls with correct aria-pressed semantics and roving tabIndex. Perfect for editors and toolbars.
const [alignment, setAlignment] = useState<"left" | "center" | "right">("center");
<ButtonGroup
toggle
segmented
segmentedStyle="control"
tone="neutral"
size="sm"
value={alignment}
onChange={(v) => setAlignment(v as any)}
aria-label="Text alignment"
>
<Button itemValue="left" iconOnly aria-label="Align left"><AlignLeft size={16} /></Button>
<Button itemValue="center" iconOnly aria-label="Align center"><AlignCenter size={16} /></Button>
<Button itemValue="right" iconOnly aria-label="Align right"><AlignRight size={16} /></Button>
</ButtonGroup>Vertical orientation is useful for tight side panels and settings stacks.
const [mode, setMode] = useState<"summary" | "notes" | "docs">("summary");
<ButtonGroup
toggle
segmented
segmentedStyle="control"
orientation="vertical"
tone="primary"
size="sm"
value={mode}
onChange={(v) => setMode(v as any)}
aria-label="Student panel"
>
<Button itemValue="summary">Summary</Button>
<Button itemValue="notes">Notes</Button>
<Button itemValue="docs">Documents</Button>
</ButtonGroup>Add an elevated surface for dense app toolbars to improve separation on busy screens.
const [range, setRange] = useState<"day" | "week" | "month">("week");
<ButtonGroup
toggle
segmented
segmentedStyle="control"
elevated
tone="primary"
size="sm"
value={range}
onChange={(v) => setRange(v as any)}
aria-label="Time range"
>
<Button itemValue="day">Day</Button>
<Button itemValue="week">Week</Button>
<Button itemValue="month">Month</Button>
</ButtonGroup>Enterprise overflow pattern for wide segmented controls without breaking layouts.
const [tab, setTab] = useState("t-1");
<ButtonGroup
toggle
segmented
segmentedStyle="control"
scrollable
tone="neutral"
size="sm"
value={tab}
onChange={(v) => setTab(v)}
aria-label="Overflow segmented control"
>
<Button itemValue="t-1">Overview</Button>
<Button itemValue="t-2">Notes</Button>
<Button itemValue="t-3">Documents</Button>
<Button itemValue="t-4">Billing</Button>
<Button itemValue="t-5">Sessions</Button>
<Button itemValue="t-6">Exports</Button>
<Button itemValue="t-7">Audit</Button>
</ButtonGroup>When segmented is false, the group behaves like a clean inline cluster with spacing.
import { ButtonGroup } from "@/design-system/components/ButtonGroup";
import { Button } from "@/design-system/components/Button";
export function Example() {
return (
<ButtonGroup segmented={false} aria-label="Inline actions">
<Button variant="primary">Create</Button>
<Button variant="outline">Export</Button>
<Button variant="ghost">Cancel</Button>
</ButtonGroup>
);
}