Segmented control
Pill-shaped toggle for switching between mutually exclusive views or modes.
SegmentedControl is a horizontal pill switcher for mutually exclusive views in the same panel — Grid / List, Monthly / Yearly, This Week / This Month. Unlike TabBar (which navigates between page sections), SegmentedControl swaps content in-place.
SegmentedControl
Use when: Toggle between 2-5 views in the same panel. Inline, compact, mutually exclusive.
Don't: Page-level navigation — that's TabBar.
<SegmentedControl items={...} />Switch
Use when: Binary on/off setting. Settings panels, feature flags.
Don't: 3+ options — use SegmentedControl.
<Switch label="..." />Select
Use when: One-of-many from a longer list (6+ options).
Don't: ≤5 options that fit horizontally — use SegmentedControl.
<Select options={...} />Use it for
- View switchers (Grid / List / Calendar)
- Pricing toggles (Monthly / Yearly)
- Date range selectors (Today / This Week / This Month)
- Mode pickers in tool panels (Edit / Preview)
Import
import { SegmentedControl } from '@brikdesigns/bds';Variants
Default
import { useState } from 'react';
const [view, setView] = useState('grid');
<SegmentedControl
value={view}
onChange={setView}
items={[
{ label: 'Grid', value: 'grid' },
{ label: 'List', value: 'list' },
]}
/>Sizes
sm— compact toolbars, dense UImd— default for forms and panelslg— prominent page-level toggles
Full-width
<SegmentedControl
value={period}
onChange={setPeriod}
size="lg"
fullWidth
items={[
{ label: 'Monthly', value: 'monthly' },
{ label: 'Yearly', value: 'yearly' },
]}
/>Many segments
SegmentedControl tolerates up to ~5 segments before the labels feel cramped. Beyond that, switch to Select.
<SegmentedControl
value={range}
onChange={setRange}
items={[
{ label: 'Today', value: 'today' },
{ label: 'Week', value: 'week' },
{ label: 'Month', value: 'month' },
{ label: 'Quarter', value: 'quarter' },
{ label: 'Year', value: 'year' },
]}
/>When not to use
Don't use SegmentedControl for page-level navigation. TabBar carries the right semantic for "navigate to a different section"; SegmentedControl is for "swap content in place." The visual treatments are similar; the navigation model is not.
- Don't use SegmentedControl for >5 options. Long pills wrap or truncate. Use Select.
- Don't use SegmentedControl for binary on/off. Use Switch — the affordance is correct.
- Don't pair with conflicting selection state. SegmentedControl is single-select; for multi-select toggles use a Checkbox group or MultiSelect.
Accessibility
- Renders a
<div role="tablist">with each segment as<button role="tab">. - The selected segment carries
aria-selected="true"; unselected carryfalse. - Keyboard arrows move selection between segments.
- Items can carry their own
aria-labelfor icon-only segments.
API
| Prop | Type | Default |
|---|---|---|
items | SegmentItem[] (required) | — |
value | string | — |
onChange | (value: string) => void | — |
size | 'sm' | 'md' | 'lg' | 'md' |
fullWidth | boolean | false |
disabled | boolean | false |
SegmentItem
interface SegmentItem {
label: ReactNode;
value: string;
disabled?: boolean;
}Related
- Switch — binary on/off
- Radio — vertical one-of-many
- Select — for >5 options
- TabBar — page-level navigation (in Storybook)
- Storybook playground