Skip to content

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.

Size
Content
Options
Layout
JSX
<SegmentedControl label="Chart view" options={options} value={view} onValueChange={setView} />
  • 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 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.
  1. 1TrackMuted pill with 4px padding.
  2. 2Selected pillLighter surface with a small shadow.
  3. 3OptionA label or a 20px icon (16px at sm). Muted until selected.
md, 40px
sm, 32px
md, icons
sm, icons
  • 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.

First selected
Last selected
Disabled
One option disabled
  • 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.

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.

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.

  • 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.
DoShort nouns that name each view.
Don'tLong labels that read as actions. Name the view, not what clicking does.
DoEvery option is an icon, each with an aria-label.
Don'tIcons and text mixed in one control. Pick one and use it for every option.
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.

  • The control is a radiogroup of radio buttons with aria-checked, using a roving tab index.
  • Give it a label, which becomes the group’s aria-label, like Chart scale.
  • Icon-only options need an ariaLabel each.
  • 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.
  • A Switch turns one setting on or off.
  • Tabs switch between different content, not views of the same content.