Content
- Sentence case, one or two words per option.
A pill switcher for two to five modes of one view, such as a date range.
import { … } from "@brdgapp/ui/components/segmented-control"SegmentedControl picks one of two to five modes for a single view: a growth chart's 12, 26 or 52 weeks, or Light and Dark. One option is always selected. The usual mistake is using it to filter a list or to switch between different content, which are FilterChip and Tabs.
Every control has a name
Every control says what it does to a screen reader. An icon-only button carries an aria-label naming the action ("Close", not "X"); a group of filters or a table has a name; a tooltip is never the only name.
Track. A pill on --surface-secondary with a 1px border.
Option. 12px SemiBold. The selected option sits on a raised white pill with a soft shadow.
The Outcomes growth chart's range.
Settings → Appearance.
| Rest | Hover | Focus | |
|---|---|---|---|
| Selected | |||
| Not selected |
| State | What happens |
|---|---|
| Selected | Raised pill, --text-primary. |
| Rest | --text-muted; hover darkens. |
| Focus visible | 2px blue ring on the option. |
aria-pressed, and arrow keys move between options.value and onChange.Do
Keep labels short and parallel: 12 weeks, 26 weeks, 52 weeks.Don't
Mix an icon-only option with text options.aria-label on the control is required: it says what is being chosen ("Time range").ariaLabel.| Keys | Action |
|---|---|
| ←→ | Move between options. |
| EnterSpace | Select the focused option. |
SegmentedControl
The switcher.
| Prop | Type | Default | Description |
|---|---|---|---|
options | { value, label, ariaLabel? }[] | — | Two to five options. |
value | string | — | The selected option. |
onChange | (value) => void | — | Called with the new option. |
aria-label | string | — | Required. What is being chosen. |
className | string | — | Layout only. |
What it's built from and where it's used, read from the code. When you change it, check these too.
Where the code still differs from the system. Follow the system, not the gap.
aria-label was optional. The package requires it, so a nameless control won't compile.components.md → SegmentedControl; src/components/ui/segmented-control.tsx.