nori-ui

SegmentedControl

Single-select switcher styled as a row of segments inside a single rounded container.

2.8 kBgzipped

At a glance

  • Compact "iOS UISegmentedControl" pattern — a row of segments inside a single rounded container, only one selected.
  • Use for binary or small (3–5) inline choices that sit next to their content. Reach for Tabs when each option owns a distinct content region.
  • Keyboard nav follows the WAI-ARIA radiogroup pattern: arrow keys move between segments (selection follows focus), Home / End jump to first / last, with wrap-around. Disabled segments are skipped.
  • Always exactly one selection. If "no selection" is a valid state, use Toggle.Group with type="single" instead.

Preview

Direction:

options

Array of segment descriptors. Each option has at least value and label; pass disabled: true to skip an option (it's still rendered, greyed out, and skipped by arrow-key navigation).

<SegmentedControl
    label="View"
    defaultValue="grid"
    options={[
        { value: 'grid', label: 'Grid' },
        { value: 'list', label: 'List' },
        { value: 'map', label: 'Map', disabled: true },
    ]}
/>

value and defaultValue

Controlled via value (paired with onChange); uncontrolled via defaultValue. The Segmented Control never falls back to "no selection" — the initial value must match one of the option values.

const [view, setView] = useState<'grid' | 'list'>('grid');
<SegmentedControl value={view} onChange={setView} options={…} />

onChange

Fires with the next value whenever the user picks a segment. Pair with value for controlled, omit for uncontrolled — the control calls it either way.

size

Density. Aligned with Button / Toggle.

ValueMin height
sm32 px
md (default)36 px
lg44 px
<SegmentedControl size="sm" options={…} />

disabled

Disables every segment in the control. Individual segments can also opt out via disabled on the option.

<SegmentedControl disabled defaultValue="grid" options={…} />

label

Accessible name for the control. Required for screen readers — it's forwarded to the radiogroup / group ARIA role and announced when focus enters the control.

<SegmentedControl label="View mode" options={…} />

Props

PropTypeDefaultDescription
options*readonly SegmentedControlOption<T>[]The set of selectable segments.
classNamestring
defaultValuestringUncontrolled initial value. Required if you don't pass `value`.
disabledbooleanfalseGroup-level disable.
labelstringHide the visible labels — when set, segments must have `aria-label`.
onChange(next: T) => voidFires when the user selects a different segment.
sizeenummdVisual size. `sm` is denser for inline filters; `md` is the default for top-of-view tab switchers. @defaultValue 'md'
testIDstring
valuestringControlled value.

On this page

Preview theme