Segmented control
A segmented control switches between views or modes of the same thing, like Price and Demand on a chart, grid and list, or light and dark.
<SegmentedControl label="Chart view" options={options} value={view} onValueChange={setView} />When to use
Section titled “When to use”- To switch how the same content is shown, like a chart’s price basis or time range.
- To pick between two to five short, related options where all of them should stay visible.
- To filter one list by a mode, like Mine and All.
When not to use
Section titled “When not to use”- When each option opens different content, like a page’s Overview and Activity, use tabs.
- To turn one setting on or off, use a switch.
- For more than five options, or labels that don’t fit on one line, use a select or a radio group.
- To start an action, use buttons.
Anatomy
Section titled “Anatomy”- 1TrackMuted pill with 4px padding.
- 2Selected pillLighter surface with a small shadow.
- 3OptionA label or a 20px icon (16px at sm). Muted until selected.
- md (40px) is the default, for controls that stand on their own, like a dialog’s Deposit and Withdraw.
- sm (32px) sits in dense headers and toolbars, like chart controls and table filters.
Each size takes text or icons. Icons are 20px at md and 16px at sm.
States
Section titled “States”- Selected sits on a lighter pill with a small shadow and full-strength text. One option is always selected.
- Unselected options use muted text, and turn full strength on hover.
- Disabled drops to 40% opacity. Disable the whole control, or a single option that doesn’t apply right now.
Full width
Section titled “Full width”Set fullWidth to split the width evenly between the options, for example across the top of a dialog. Otherwise each option is as wide as its label.
Narrow space
Section titled “Narrow space”A 280px column, like a report form on a phone. Swipe, scroll or use the arrow keys.
When the options are wider than the space, the track scrolls sideways instead of wrapping. The scrollbar stays hidden, the edge with more options fades out, and picking an option scrolls it fully into view. Keep labels short so most screens show every option without scrolling.
Content
Section titled “Content”- Name each view with a short noun, like Price, Bids or 1W. One or two words.
- Use sentence case and no full stop.
- Keep every option the same kind: all text or all icons. Icon-only options need an
ariaLabel. - A segmented control never wraps. On a narrow screen it scrolls sideways and fades the edge that has more options, so keep labels short enough that most screens show them all.
Behaviour
Section titled “Behaviour”| Key | Action |
|---|---|
| Tab | Moves focus to the selected option. The control is one tab stop. |
| ← → (or ↑ ↓) | Selects the previous or next option, wrapping at the ends. |
| Home / End | Selects the first or last option. |
Clicking an option selects it. The pill glides to the new option with a small spring, and the label turns full strength as the pill covers it. Arrow keys move the pill straight to the next option without gliding, so fast keyboard use never lags, and they skip disabled options. Under reduced motion the pill never glides. When the options are wider than the space, the track scrolls sideways and keeps the selected option in view.
Selection happens on focus, so the view should change at once. If switching loads slowly, show the loading state inside the view, not on the control.
Accessibility
Section titled “Accessibility”- The control is a
radiogroupofradiobuttons witharia-checked, using a roving tab index. - Give it a
label, which becomes the group’saria-label, like Chart scale. - Icon-only options need an
ariaLabeleach. - Keyboard focus shows a 2px ring with a 2px gap (
focus/ring), the same as the button. - The selected option sits on its own pill, so it doesn’t rely on text colour alone.
| Prop | Type | Default | Notes |
|---|---|---|---|
options |
{ value, label?, icon?, ariaLabel?, disabled? }[] |
Required | Two to five options. |
value |
string |
Required | The selected option’s value. |
onValueChange |
(value) => void |
Required | Called with the new value. |
label |
string |
Required | Names the group for screen readers. |
size |
"md" | "sm" |
"md" |
40px or 32px tall. |
fullWidth |
boolean |
false |
Fills the container and splits it evenly. |
disabled |
boolean |
false |
Dims the whole control and takes it out of the tab order. |
className |
string |
Added to the track. |
Related
Section titled “Related”- A Switch turns one setting on or off.
- Tabs switch between different content, not views of the same content.