Forms
Segmented
A segmented control: one visible choice from a few, always all on screen.
Import
import { Segmented } from '@the_viveksingh/vivek-ui'A view switcher with real radio semantics
This is not Tabs. A segmented control reveals nothing and hides nothing - it is one visible choice from a few, so it is a styled radiogroup: one tab stop, arrows move and select together, aria-checked on the active segment.
Showing the list view. Tab reaches the checked segment; arrows move and select in one keystroke, because a radio you land on is a radio you chose.
const [view, setView] = useState('list')
<Segmented
label="View"
value={view}
onValueChange={setView}
options={[
{ value: 'list', label: 'List' },
{ value: 'board', label: 'Board' },
{ value: 'timeline', label: 'Timeline' },
]}
/>
// fullWidth stretches segments evenly; disabled works per option:
<Segmented fullWidth label="Range" defaultValue="30d" options={[
{ value: '7d', label: '7 days' },
{ value: '30d', label: '30 days' },
{ value: 'all', label: 'All time', disabled: true },
]} />Three sizes
sm, md and lg, matching every other control in the library.
<Segmented size="sm" label="Zoom" defaultValue="day" options={options} />
<Segmented size="md" label="Zoom" defaultValue="day" options={options} />
<Segmented size="lg" label="Zoom" defaultValue="day" options={options} />Props
Generated from the package's own type declarations, so this table cannot drift from the code.
| Prop | Type | Default | Description |
|---|---|---|---|
options required | readonly SegmentedOption[] | — | — |
label required | string | — | Required. The group has no visible name — the segments label themselves, not the choice being made — so without this a screen reader announces "radio group" and nothing else. |
value | string | — | Controlled selection. |
defaultValue | string | — | Uncontrolled initial selection. Omit it and nothing starts selected. |
onValueChange | (value: string) => void | — | — |
size | 'sm' | 'md' | 'lg' | — | — |
fullWidth | boolean | — | Stretch to the container, splitting the width equally between segments. |
disabled | boolean | — | — |
Every remaining prop is spread onto the root element, so all standard HTML and ARIA attributes work. className and style are merged with the library's own, never replaced, and the ref forwards to the root DOM node.
Rendering
Segmented declares 'use client' because it needs state, effects or event handlers. Importing it into a Server Component creates a client boundary at this component — everything above it stays on the server.