/// Inputs
SegmentedControl
Compact single-select toggle — a bordered row of mono uppercase segments where the active one inverts to a solid fill.
import { SegmentedControl } from "@protocore/pds";Basics
Pass items and control the selection via value / onValueChange. Exactly one segment is always active — onValueChange never fires with an empty value.
Icon segments
Segments accept any ReactNode label. For icon-only segments, give each icon an aria-label and the control an aria-label for the group.
Disabled segment
Disable a single segment with disabled on the item, or the whole control with the top-level disabled prop.
When to use it
Use a SegmentedControl for 2–4 short, mutually-exclusive options that switch a view or scope in place — a time range, a layout mode, an environment. It's the compact cousin of RadioGroup: prefer RadioGroup when options are longer or need descriptions, and Select once they outgrow a row. It differs from FilterBar in intent — a segmented control picks one *mode*, while a FilterBar toggles filters (often many) over a collection. It is not a Switch: use Switch for a single on/off setting.
Usage
Do
- Keep to 2–4 segments with short, parallel labels.
- Give the control an `aria-label`, especially with icon-only segments.
- Use it to switch a view or scope that updates immediately.
- Keep exactly one segment meaningful as the default selection.
Don't
- Don't exceed ~4 segments — the row gets cramped; use Select or RadioGroup.
- Don't use long or wrapping labels; a segment is not a menu item.
- Don't use it for multi-select — that's a FilterBar or Checkbox set.
- Don't use it for a binary on/off setting — that's a Switch.
Accessibility
| Keys | Action |
|---|---|
| Tab | Move focus into the group, landing on the active segment. |
| Arrow Left / Right | Move to and select the previous / next enabled segment. |
| Home / End | Move to and select the first / last enabled segment. |
| Space / Enter | Select the focused segment. |
- Built on Radix ToggleGroup (`type="single"`) with radiogroup semantics and roving tabindex — one Tab stop.
- Disabled segments are skipped during arrow navigation.
- Icon-only segments must carry their own label; the control needs an `aria-label` for the group name.
SegmentedControl props
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | string | — | Accessible name for the radio group (required for icon-only segments). |
className | string | — | |
defaultValue | string | — | Uncontrolled initial selected value. |
disabled | boolean | — | Disable the whole control. |
items * | SegmentedControlItem[] | — | The segments, left to right. |
onValueChange | ((value: string) => void) | — | Fired with the newly-selected value (never with an empty string — a segmented control always keeps one segment active). |
style | CSSProperties | — | |
value | string | — | Controlled selected value. |