SegmentedControl
<SegmentedControl> is a row of buttons where exactly one is selected. Use for view-axis toggles, period filters, scope switches — anything with two-to-five visible-at-once choices. ViewSwitcher composes this primitive.
When to use
- View toggles (List / Grid / Board).
- Time-period filters (Day / Week / Month / Year).
- Scope filters (Mine / Team / All).
Don’t use SegmentedControl for: more than 5 options (Select), boolean toggles (Switch), or commands (Button group).
Default
<SegmentedControl ariaLabel="View" defaultValue="list" options={[ { value: 'list', label: 'List' }, { value: 'grid', label: 'Grid' }, { value: 'board', label: 'Board' }, ]}/>With icons
<SegmentedControl ariaLabel="View" defaultValue="list" options={[ { value: 'list', label: 'List', icon: IconList }, { value: 'grid', label: 'Grid', icon: IconLayoutGrid }, { value: 'board', label: 'Board', icon: IconLayoutKanban }, ]}/>With counts
<SegmentedControl ariaLabel="Folder" defaultValue="inbox" options={[ { value: 'inbox', label: 'Inbox', count: 12 }, { value: 'starred', label: 'Starred', count: 3 }, { value: 'archive', label: 'Archive', count: 0 }, ]}/>Small
For inline toolbar density.
<SegmentedControl size="sm" … />Controlled
Active value: list
const [value, setValue] = useState('list');
<SegmentedControl ariaLabel="View" value={value} onValueChange={setValue} options={[…]}/>API
| Prop | Type | Default | Description |
|---|---|---|---|
options * | SegmentedControlOption<TValue>[] | — | Two-to-five options. Each: { value, label, icon?, count?, disabled? }. |
value | TValue | — | Controlled active value. Pair with onValueChange. |
defaultValue | TValue | — | Initial value for uncontrolled mode. |
onValueChange | (value: TValue) => void | — | Fires when the user picks a different segment. Doesn't fire when re-clicking the active segment. |
ariaLabel * | string | — | Describes the choice axis ("View", "Period", "Scope") for screen readers. |
size | "sm" | "default" | "default" | Inline-toolbar density vs. form-row density. |
disabled | boolean | false | Disable every option. |
className | string | — | Forwarded to the root. |
Design guidelines
✓ Do
- Keep labels short — one or two words. Long labels stretch the control out of proportion.
- Order options by frequency of use, left to right. Don't sort alphabetically.
- Use `size="sm"` inside toolbars; default everywhere else.
✗ Don't
- Add a 6th option. The pattern caps at five for visual + cognitive reasons; switch to Select.
- Use SegmentedControl for boolean toggles — that's a Switch.
- Mix icon-only and label-only segments in the same control. Pick one or the other.
Accessibility
- Composes Radix
ToggleGroup(type="single") — exposesrole="radiogroup"with properradioitems. - Keyboard: Tab to focus, ←/→ to move between items, Enter / Space to select.
ariaLabelis required — without it the choice axis has no name.- Color is never the only signal — the active state has its own background + shadow.
Related
ViewSwitcher— Composes SegmentedControl with a body slot per view.Switch— For boolean toggles.Select— When you outgrow 5 options.