static/app/components/core/segmentedControl/segmentedControl.mdx
import {Fragment, useState} from 'react';
import {SegmentedControl} from '@sentry/scraps/segmentedControl';
import {IconStats} from 'sentry/icons'; import * as Storybook from 'sentry/stories';
export const documentation = import('!!type-loader!@sentry/scraps/segmentedControl');
<SegmentedControl> is a group of buttons that work together as a single control for selecting one option from a set. It provides a compact, visual way to switch between different views, modes, or filter options.
Use <SegmentedControl> as an alternative to tabs or radio buttons when you need a more compact, button-like appearance for switching between options.
const [value, setValue] = useState('one');
<SegmentedControl value={value} onChange={setValue}>
<SegmentedControl.Item key="one">Option 1</SegmentedControl.Item>
<SegmentedControl.Item key="two">Option 2</SegmentedControl.Item>
<SegmentedControl.Item key="three">Option 3</SegmentedControl.Item>
</SegmentedControl>;
<SegmentedControl> is a controlled component. Manage the selected value in state and update it via the onChange callback.
export function BasicDemo() { const [value, setValue] = useState('two'); return ( <Fragment> <p>Selected: {value}</p> <SegmentedControl value={value} onChange={setValue}> <SegmentedControl.Item key="one">One</SegmentedControl.Item> <SegmentedControl.Item key="two">Two</SegmentedControl.Item> <SegmentedControl.Item key="three">Three</SegmentedControl.Item> </SegmentedControl> </Fragment> ); }
<Storybook.Demo> <BasicDemo /> </Storybook.Demo>
const [value, setValue] = useState('two');
<SegmentedControl value={value} onChange={setValue}>
<SegmentedControl.Item key="one">One</SegmentedControl.Item>
<SegmentedControl.Item key="two">Two</SegmentedControl.Item>
<SegmentedControl.Item key="three">Three</SegmentedControl.Item>
</SegmentedControl>;
<SegmentedControl> supports three sizes: md (default), sm, and xs.
export function SizesDemo() { const [value, setValue] = useState('two'); return ( <Storybook.Grid> <SegmentedControl size="md" value={value} onChange={setValue}> <SegmentedControl.Item key="one">Medium</SegmentedControl.Item> <SegmentedControl.Item key="two">Default</SegmentedControl.Item> <SegmentedControl.Item key="three">Size</SegmentedControl.Item> </SegmentedControl> <SegmentedControl size="sm" value={value} onChange={setValue}> <SegmentedControl.Item key="one">Small</SegmentedControl.Item> <SegmentedControl.Item key="two">Size</SegmentedControl.Item> <SegmentedControl.Item key="three">Here</SegmentedControl.Item> </SegmentedControl> <SegmentedControl size="xs" value={value} onChange={setValue}> <SegmentedControl.Item key="one">Extra</SegmentedControl.Item> <SegmentedControl.Item key="two">Small</SegmentedControl.Item> <SegmentedControl.Item key="three">Size</SegmentedControl.Item> </SegmentedControl> </Storybook.Grid> ); }
<Storybook.Demo> <SizesDemo /> </Storybook.Demo>
<SegmentedControl size="md" value={value} onChange={setValue}>
</SegmentedControl>
<SegmentedControl size="sm" value={value} onChange={setValue}>
</SegmentedControl>
<SegmentedControl size="xs" value={value} onChange={setValue}>
</SegmentedControl>
Use the priority prop to control the visual style: default (outlined) or primary (filled).
export function PrioritiesDemo() { const [value, setValue] = useState('two'); return ( <Storybook.SideBySide> <SegmentedControl priority="default" value={value} onChange={setValue}> <SegmentedControl.Item key="one">Default</SegmentedControl.Item> <SegmentedControl.Item key="two">Priority</SegmentedControl.Item> <SegmentedControl.Item key="three">Here</SegmentedControl.Item> </SegmentedControl> <SegmentedControl priority="primary" value={value} onChange={setValue}> <SegmentedControl.Item key="one">Primary</SegmentedControl.Item> <SegmentedControl.Item key="two">Priority</SegmentedControl.Item> <SegmentedControl.Item key="three">Here</SegmentedControl.Item> </SegmentedControl> </Storybook.SideBySide> ); }
<Storybook.Demo> <PrioritiesDemo /> </Storybook.Demo>
<SegmentedControl priority="default" value={value} onChange={setValue}>
</SegmentedControl>
<SegmentedControl priority="primary" value={value} onChange={setValue}>
</SegmentedControl>
Items can include icons using the icon prop:
export function IconsDemo() { const [value, setValue] = useState('two'); return ( <SegmentedControl value={value} onChange={setValue}> <SegmentedControl.Item key="one" icon={<IconStats />}> With Icon </SegmentedControl.Item> <SegmentedControl.Item key="two" icon={<IconStats />}> And Label </SegmentedControl.Item> <SegmentedControl.Item key="three" icon={<IconStats />} aria-label="Icon Only" /> </SegmentedControl> ); }
<Storybook.Demo> <IconsDemo /> </Storybook.Demo>
<SegmentedControl value={value} onChange={setValue}>
<SegmentedControl.Item key="list" icon={<IconList />}>
List
</SegmentedControl.Item>
<SegmentedControl.Item key="grid" icon={<IconGrid />}>
Grid
</SegmentedControl.Item>
<SegmentedControl.Item key="chart" icon={<IconChart />} aria-label="Chart View" />
</SegmentedControl>
[!IMPORTANT] When using icon-only items (without text children), always provide
aria-labelfor accessibility.
Disable individual items using the disabled prop on <SegmentedControl.Item>:
export function DisabledDemo() { const [value, setValue] = useState('two'); return ( <SegmentedControl value={value} onChange={setValue}> <SegmentedControl.Item key="one">Enabled</SegmentedControl.Item> <SegmentedControl.Item key="two">Active</SegmentedControl.Item> <SegmentedControl.Item key="three" disabled> Disabled </SegmentedControl.Item> </SegmentedControl> ); }
<Storybook.Demo> <DisabledDemo /> </Storybook.Demo>
<SegmentedControl value={value} onChange={setValue}>
<SegmentedControl.Item key="one">Enabled</SegmentedControl.Item>
<SegmentedControl.Item key="two" disabled>
Disabled
</SegmentedControl.Item>
</SegmentedControl>
Add tooltips to items for additional context:
<SegmentedControl value={value} onChange={setValue}>
<SegmentedControl.Item key="one" tooltip="Show list view">
List
</SegmentedControl.Item>
<SegmentedControl.Item key="two" tooltip="Show grid view">
Grid
</SegmentedControl.Item>
</SegmentedControl>
The most common use case is switching between different view modes:
const [view, setView] = useState('list');
<SegmentedControl value={view} onChange={setView}>
<SegmentedControl.Item key="list" icon={<IconList />}>
List
</SegmentedControl.Item>
<SegmentedControl.Item key="grid" icon={<IconGrid />}>
Grid
</SegmentedControl.Item>
<SegmentedControl.Item key="chart" icon={<IconChart />}>
Chart
</SegmentedControl.Item>
</SegmentedControl>;
Use for selecting time ranges or periods:
<SegmentedControl value={range} onChange={setRange}>
<SegmentedControl.Item key="1h">1H</SegmentedControl.Item>
<SegmentedControl.Item key="24h">24H</SegmentedControl.Item>
<SegmentedControl.Item key="7d">7D</SegmentedControl.Item>
<SegmentedControl.Item key="30d">30D</SegmentedControl.Item>
</SegmentedControl>
Control visualization or display modes:
<SegmentedControl value={mode} onChange={setMode} size="sm">
<SegmentedControl.Item key="auto">Auto</SegmentedControl.Item>
<SegmentedControl.Item key="light">Light</SegmentedControl.Item>
<SegmentedControl.Item key="dark">Dark</SegmentedControl.Item>
</SegmentedControl>
Choose the right component for your use case:
<SegmentedControl> meets WCAG 2.2 AA standards:
Labels
aria-label<div>
<label id="view-label">View Mode</label>
<SegmentedControl value={view} onChange={setView} aria-labelledby="view-label">
<SegmentedControl.Item key="list">List</SegmentedControl.Item>
<SegmentedControl.Item key="grid">Grid</SegmentedControl.Item>
</SegmentedControl>
</div>
Keyboard Navigation
For more information, see button and radio group accessibility patterns.