Segmented Control
A segmented control switches between a few options, such as views of the same content, with exactly one always selected.A segmented control shows a small set of options in one bar and keeps exactly one selected, such as list or grid for the same items. Changing the selection changes what people see straight away. Switching between separate panels of content is Tabs, and a choice inside a form is a Radio Group.
Playground
Usage
import { Flex, Heading, SegmentedControl } from '@kushagradhawan/kookie-ui';
export function ProjectsHeader({ view, setView }: { view: string; setView: (view: string) => void }) {
return (
<Flex justify="between" align="center">
<Heading size="4">Projects</Heading>
<SegmentedControl.Root value={view} onValueChange={setView} aria-label="View">
<SegmentedControl.Item value="list">List</SegmentedControl.Item>
<SegmentedControl.Item value="grid">Grid</SegmentedControl.Item>
<SegmentedControl.Item value="board">Board</SegmentedControl.Item>
</SegmentedControl.Root>
</Flex>
);
}Anatomy
<SegmentedControl.Root>
<SegmentedControl.Item value="a">Option</SegmentedControl.Item>
</SegmentedControl.Root>- SegmentedControl.Root: The bar. It holds the selected value and draws the indicator that slides to the selected item.
- SegmentedControl.Item: One option. Its text or icon is the label.
Best practices
Keep it to two to five options. Every option shares one bar, so each one gets narrower as you add more. For a longer list, use a Select.
Use one or two words per label. Items share the width evenly, and a long label makes the whole bar wide. Use nouns of the same kind, such as "Day, Week, Month".
Always start with a value selected. One option is always on, and people can't clear it by pressing it again. Set defaultValue or value so the bar never renders empty.
Change the view at once. A segmented control filters or rearranges what is on screen now. Don't use it for a choice that waits for a save button, which is a Radio Group.
Don't use it for actions. Each item selects a state. An action such as "Export" is a Button, and an on or off state such as bold is a Toggle.
Variant
variant sets the bar's look. soft is the default, a filled track. raised and outline wear the edge of a TextField of the same variant, with a soft indicator inside, so a panel of fields has no filled track in it.
Size
size picks one of four heights: 28, 32, 40 and 48 pixels. Size 2 is the default. The bar is as tall as a Button of the same size, so it lines up in a toolbar. size accepts a responsive object, such as { initial: '3', md: '2' }.
Orientation
orientation="vertical" stacks the items in a column, and the indicator slides up and down. Use it with iconOnly items in a narrow side panel, where short square items fit. Text labels in a vertical bar read poorly unless they are one short word. orientation accepts a responsive object.
Examples
Icon only
iconOnly makes each item a square as wide as it is tall. The item has no visible text, so give each one an aria-label.
<SegmentedControl.Root defaultValue="left" aria-label="Text alignment">
<SegmentedControl.Item value="left" iconOnly aria-label="Align left">
<HugeiconsIcon icon={TextAlignLeftIcon} strokeWidth={1.75} />
</SegmentedControl.Item>
<SegmentedControl.Item value="center" iconOnly aria-label="Align centre">
<HugeiconsIcon icon={TextAlignCenterIcon} strokeWidth={1.75} />
</SegmentedControl.Item>
<SegmentedControl.Item value="right" iconOnly aria-label="Align right">
<HugeiconsIcon icon={TextAlignRightIcon} strokeWidth={1.75} />
</SegmentedControl.Item>
</SegmentedControl.Root>Icon and label
Put the icon before the text, inside the item. The item sizes the icon, so don't size it yourself.
<SegmentedControl.Root defaultValue="grid" aria-label="View">
<SegmentedControl.Item value="list">
<HugeiconsIcon icon={Menu01Icon} strokeWidth={1.75} />
List
</SegmentedControl.Item>
<SegmentedControl.Item value="grid">
<HugeiconsIcon icon={GridViewIcon} strokeWidth={1.75} />
Grid
</SegmentedControl.Item>
</SegmentedControl.Root>Time range
A row of periods above a chart is a common use. The chart redraws as soon as the selection changes.
<SegmentedControl.Root value={range} onValueChange={setRange} aria-label="Time range">
<SegmentedControl.Item value="day">Day</SegmentedControl.Item>
<SegmentedControl.Item value="week">Week</SegmentedControl.Item>
<SegmentedControl.Item value="month">Month</SegmentedControl.Item>
<SegmentedControl.Item value="year">Year</SegmentedControl.Item>
</SegmentedControl.Root>Props
SegmentedControl.Root
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | The selected value, controlled | |
defaultValue | string | The selected value at first render | |
onValueChange | (value: string) => void | Fires with the new value. It never fires with an empty value | |
variant | 'soft' | 'raised' | 'outline' | 'soft' | The look of the bar |
size | '1' | '2' | '3' | '4', responsive | '2' | The height step |
orientation | 'horizontal' | 'vertical', responsive | 'horizontal' | The direction of the bar |
radius | 'none' | 'small' | 'medium' | 'large' | 'full' | Theme radius | The corner |
disabled | boolean | false | Disables every item |
SegmentedControl.Root also accepts every attribute of the HTML div element.
SegmentedControl.Item
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | Required. The value this item selects | |
iconOnly | boolean | false | Square, icon only. Give the item an aria-label |
disabled | boolean | false | Stops this item from being selected |
SegmentedControl.Item also accepts every attribute of the HTML button element.
Accessibility
| Key | Action |
|---|---|
| Tab | Moves focus into the bar, onto the selected item, and out again |
| Arrow keys | Move to the next or previous item and select it |
| Home or End | Moves to the first or last item and selects it |
| Space or Enter | Selects the focused item |
- Name: Give the root an
aria-label, such as "View". Each item takes its name from its text, or from itsaria-labelwhen it is icon only. - State: The root has
role="radiogroup"and each item hasrole="radio". A screen reader announces the item, whether it is selected, and its position in the group. - Focus: The bar is one tab stop. Arrow keys select as they move, as in a radio group.
- Disabled: A disabled bar sets
disabledon every item, which removes them from the tab order. Arrow keys skip a disabled item.