Controlsregistry/ui/segmented-control.tsx/r/segmented-control.json
SegmentedControl
Exposure-sheet cell selector with a mix-blend-mode: difference indicator that steps across cells in 3 held poses.
Light · Paper.f12-theme-light
Interactive previewSelected: 7 days
Dark · Flashback.f12-theme-dark
Interactive previewSelected: 7 days
Install & copy-in source
shadcn CLI (segmented-control.json)
npx shadcn@latest add https://frame12.dev/r/segmented-control.jsonUsage example (SegmentedControl)
import { SegmentedControl } from '@/components/frame12';
export function RangeSelector({ range, setRange }: { range: number; setRange: (r: number) => void }) {
return (
<SegmentedControl
ariaLabel="Date range"
options={[
{ value: 7, label: '7', unit: 'days' },
{ value: 30, label: '30', unit: 'days' },
{ value: 90, label: '90', unit: 'days' },
]}
value={range}
onChange={setRange}
/>
);
}WCAG AAAccessibility guarantees
Accessibility notes
- Uses role="group" with aria-pressed={active} on native <button type="button"> elements.
- Provides a 3px solid --f-marker inset focus ring on :focus-visible.
GrammarFRAME/12 rules
Design grammar
- In .f12-m-stepped mode, the indicator transitions with steps(3, end) over 250ms (3 held poses at 83.33ms).
- Uses mix-blend-mode: difference so text covered by the indicator remains legible at every intermediate pose.
Props & TypeScript API
| Prop | Type | Default | Description |
|---|---|---|---|
options | Array<{ value: T; label: string; unit?: string }> | required | Ordered cell options with display numeral/label and optional mono unit. |
value | T | required | Currently active option value. |
onChange | (value: T) => void | required | Callback fired when a cell is activated. |
ariaLabel | string | 'Options' | Accessible label for the role="group" container. |
idPrefix | string | 'seg' | Prefix for deterministic button IDs (${idPrefix}-${opt.value}). |