Segmented control
A row of buttons for switching between two to five related options, such as views or periods. Exactly one is pressed. To show different panels, use Tabs.
$12 per month
Code
demo.tsx
import {Stack, Text, SegmentedControl} from '@earendil-works/elanor-react';
import {useState} from 'react';
export default function SegmentedControlDemo() {
const [period, setPeriod] = useState(['monthly']);
return (
<Stack gap="small" align="start">
<SegmentedControl.Root
aria-label="Billing period"
value={period}
onValueChange={(next) => {
if (next.length > 0) setPeriod(next);
}}
>
<SegmentedControl.Item value="monthly">Monthly</SegmentedControl.Item>
<SegmentedControl.Item value="yearly">Yearly</SegmentedControl.Item>
</SegmentedControl.Root>
<Text role="status">{period[0] === 'yearly' ? '$120 per year' : '$12 per month'}</Text>
</Stack>
);
} Usage
import {SegmentedControl} from '@earendil-works/elanor-react';
<SegmentedControl.Root aria-label="Billing period" defaultValue={['monthly']}>
<SegmentedControl.Item value="monthly">Monthly</SegmentedControl.Item>
<SegmentedControl.Item value="yearly">Yearly</SegmentedControl.Item>
</SegmentedControl.Root>;
The value is an array with one item, as in Base UI Toggle Group. Pressing the selected item would clear it; ignore empty values in onValueChange to keep one selected, as the demo does.
Density
Use compact on Root beside compact controls, such as Dropdown filters in a search and filter bar. Each item’s touch target keeps the default height, as on compact Dropdown triggers.
Code
density.tsx
import {SegmentedControl, Stack} from '@earendil-works/elanor-react';
export default function SegmentedControlDensity() {
return (
<Stack direction="row" gap="large" wrap="wrap">
{(['default', 'compact'] as const).map((density) => (
<SegmentedControl.Root
key={density}
density={density}
aria-label={density === 'default' ? 'Billing period, default' : 'Billing period, compact'}
defaultValue={['monthly']}
>
<SegmentedControl.Item value="monthly">Monthly</SegmentedControl.Item>
<SegmentedControl.Item value="yearly">Yearly</SegmentedControl.Item>
</SegmentedControl.Root>
))}
</Stack>
);
} API
SegmentedControl.Root
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | 'horizontal' | - | Only horizontal is supported. |
multiple | false | - | One item is pressed at a time. |
density | 'compact' | 'default' | 'default' | compact removes the items' block padding but keeps their touch target height. |
Also accepts Base UI ToggleGroup props.
SegmentedControl.Item
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'submit' | 'reset' | 'button' | 'button' |
Also accepts Base UI Toggle props.