components / segmented-control
SegmentedControl
A single choice among a few options, to switch between views of the same content.
How to use
Place `SegmentedItem`s inside a `SegmentedControl`. It is a `radiogroup`: one item is always selected, arrows move and select (skipping disabled items), and `aria-label` is required. Works controlled (`value`) or uncontrolled (`defaultValue`). For navigating between sections use `Tabs`.
preview
SegmentedControl.tsx
import { SegmentedControl, SegmentedItem } from "vaiperui"; <SegmentedControl aria-label="View" defaultValue="list"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem> <SegmentedItem value="map">Map</SegmentedItem></SegmentedControl>Colors
preview
colors.tsx
<SegmentedControl aria-label="…" defaultValue="list" variantColor="primary"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" variantColor="success"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" variantColor="warning"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" variantColor="danger"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl>Sizes
preview
sizes.tsx
<SegmentedControl aria-label="…" defaultValue="list" size="sm"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" size="md"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" size="lg"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl>Radius
preview
radius.tsx
<SegmentedControl aria-label="…" defaultValue="list" radius="none"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" radius="sm"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" radius="md"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" radius="lg"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" radius="full"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl>Custom color
preview
custom-color.tsx
<SegmentedControl aria-label="…" defaultValue="list" customColor="#f97316"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl> <SegmentedControl aria-label="…" defaultValue="list" customColor="#8b5cf6"> <SegmentedItem value="list">List</SegmentedItem> <SegmentedItem value="grid">Grid</SegmentedItem></SegmentedControl>States
preview
states.tsx
<SegmentedControl aria-label="…" disabled>…</SegmentedControl>Props
| Prop | Values | Default | Description |
|---|---|---|---|
| aria-label | string | required | Names what the control selects |
| value | string | none | Selected item (controlled) |
| defaultValue | string | none | Initial item (uncontrolled) |
| onValueChange | (value: string) => void | none | Called when the selection changes |
| disabled | boolean | false | Disables the whole control |
| variantColor / customColor | ControlColors | CustomColor | neutral | Color of the selected item's text; neutral when neither is set |
| size | sm | md | lg | md | Size of the control and its text |
| radius | none | sm | md | lg | full | md | Corner rounding |
| animation | none | smooth | fast | bounce | smooth | Transition between states |
| SegmentedItem: value, disabled | string, boolean | none | The item's value; disables only this item |
Accessibility
- The container has `role="radiogroup"`, and `aria-disabled` when the whole control is `disabled`.
- Each `SegmentedItem` is a button with `role="radio"` and `aria-checked`.
- Roving tabindex: only the selected item is in the Tab order (`tabIndex=0`).
- Arrow keys move focus and select at once, wrap around, and skip disabled items.
Keyboard
| Key | Action |
|---|---|
| Tab | Moves focus into and out of the group (to the selected item). |
| Right / Down | Selects the next enabled item. |
| Left / Up | Selects the previous enabled item. |
| Enter / Space | Selects the focused item (native button click). |
Keep in mind
- Pass an `aria-label` or `aria-labelledby` on `SegmentedControl`; the component does not add a name to the group.
- Pass `value` or `defaultValue`; with no selected item every item has `tabIndex=-1` and the group is unreachable by keyboard.
- Home and End are not handled.