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

PropTypeDefaultDescription
valuestringThe selected value, controlled
defaultValuestringThe selected value at first render
onValueChange(value: string) => voidFires 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 radiusThe corner
disabledbooleanfalseDisables every item

SegmentedControl.Root also accepts every attribute of the HTML div element.

SegmentedControl.Item

PropTypeDefaultDescription
valuestringRequired. The value this item selects
iconOnlybooleanfalseSquare, icon only. Give the item an aria-label
disabledbooleanfalseStops this item from being selected

SegmentedControl.Item also accepts every attribute of the HTML button element.

Accessibility

KeyAction
TabMoves focus into the bar, onto the selected item, and out again
Arrow keysMove to the next or previous item and select it
Home or EndMoves to the first or last item and selects it
Space or EnterSelects the focused item
  • Name: Give the root an aria-label, such as "View". Each item takes its name from its text, or from its aria-label when it is icon only.
  • State: The root has role="radiogroup" and each item has role="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 disabled on every item, which removes them from the tab order. Arrow keys skip a disabled item.