SegmentedButton

Use SegmentedButton to arrange related controls in a single pill-shaped row.

React

Group

Use Group for independent action buttons with no shared selection state. Items default to ghost.

live

<Box
_dark={{ bgColor: 'background.primary' }}
alignItems="flex-start"
bgColor="background.primaryInvert"
borderRadius="400"
display="flex"
p="500"
>
<SegmentedButton.Group>
<SegmentedButton.Item icon={iconPlus} label="Zoom in" onClick={() => {}} />
<SegmentedButton.Item
icon={iconMinus}
label="Zoom out"
onClick={() => {}}
/>
</SegmentedButton.Group>
</Box>

Group variant

Pass variant on the group to set the track background color. Items are unaffected—they stay ghost unless each item sets its own variant.

live

<Box
_dark={{ bgColor: 'background.primary' }}
alignItems="flex-start"
bgColor="background.primaryInvert"
borderRadius="400"
display="flex"
p="500"
>
<SegmentedButton.Group variant="primary">
<SegmentedButton.Item icon={iconPlus} label="Add" onClick={() => {}} />
<SegmentedButton.Item icon={iconGrip} label="Grid" onClick={() => {}} />
<SegmentedButton.Item icon={iconMinus} label="Remove" onClick={() => {}} />
</SegmentedButton.Group>
</Box>

Group item variant

Pass variant on individual items to style them differently. Items without a variant stay ghost.

live

<Box
_dark={{ bgColor: 'background.primary' }}
alignItems="flex-start"
bgColor="background.primaryInvert"
borderRadius="400"
display="flex"
p="500"
>
<SegmentedButton.Group>
<SegmentedButton.Item
icon={iconPlus}
label="Zoom in"
onClick={() => {}}
variant="primary"
/>
<SegmentedButton.Item
icon={iconMinus}
label="Zoom out"
onClick={() => {}}
variant="secondary"
/>
</SegmentedButton.Group>
</Box>

Mixed icon and label

live

<Box
_dark={{ bgColor: 'background.primary' }}
alignItems="flex-start"
bgColor="background.primaryInvert"
borderRadius="400"
display="flex"
p="500"
>
<SegmentedButton.Group>
<SegmentedButton.Item
icon={iconPlus}
label="Add"
onClick={() => {}}
variant="primary"
/>
<SegmentedButton.Item onClick={() => {}} variant="secondary">
Reset
</SegmentedButton.Item>
<SegmentedButton.Item
icon={iconGrip}
label="Grid"
onClick={() => {}}
variant="secondary"
/>
</SegmentedButton.Group>
</Box>

Image button

Place a custom element directly inside Group to render a non-standard control—for example a circular image button. Match the item height with boxSize="400" and borderRadius="full" so it lines up with the other buttons.

live

<Box
_dark={{ bgColor: 'background.primary' }}
alignItems="flex-start"
bgColor="background.primaryInvert"
borderRadius="400"
display="flex"
p="500"
>
<SegmentedButton.Group>
<SegmentedButton.Item icon={iconPlus} label="Zoom in" onClick={() => {}} />
<SegmentedButton.Item icon={iconGrip} label="Grid" onClick={() => {}} />
<Image
alt="Select cat"
borderRadius="full"
boxSize="400"
cursor="pointer"
flexShrink={0}
objectFit="cover"
onClick={() => {}}
role="button"
src="https://placecats.com/300/200"
tabIndex={0}
/>
</SegmentedButton.Group>
</Box>

Sizes

Group accepts size="medium" (default), "small", or "xs".

live

<Box
_dark={{ bgColor: 'background.primary' }}
alignItems="flex-start"
bgColor="background.primaryInvert"
borderRadius="400"
display="flex"
p="500"
>
<Stack direction="column" spacing="300">
<SegmentedButton.Group size="medium">
<SegmentedButton.Item icon={iconGrip} label="Grid" onClick={() => {}} />
<SegmentedButton.Item
icon={iconCellPhone}
label="Phone"
onClick={() => {}}
/>
<SegmentedButton.Item
icon={iconMinus}
label="Remove"
onClick={() => {}}
/>
</SegmentedButton.Group>
<SegmentedButton.Group size="small">
<SegmentedButton.Item icon={iconGrip} label="Grid" onClick={() => {}} />
<SegmentedButton.Item
icon={iconCellPhone}
label="Phone"
onClick={() => {}}
/>
<SegmentedButton.Item
icon={iconMinus}
label="Remove"
onClick={() => {}}
/>
</SegmentedButton.Group>
<SegmentedButton.Group size="xs">
<SegmentedButton.Item icon={iconGrip} label="Grid" onClick={() => {}} />
<SegmentedButton.Item
icon={iconCellPhone}
label="Phone"
onClick={() => {}}
/>
<SegmentedButton.Item
icon={iconMinus}
label="Remove"
onClick={() => {}}
/>
</SegmentedButton.Group>
</Stack>
</Box>

Color mode

Use colorMode="light" when placing the component on a dark surface.

live

<Stack alignItems="flex-start" bgColor="neutral.875" borderRadius="400" p="500">
<SegmentedButton.Group colorMode="light">
<SegmentedButton.Item icon={iconGrip} label="Grid" onClick={() => {}} />
<SegmentedButton.Item
icon={iconCellPhone}
label="Phone"
onClick={() => {}}
/>
<SegmentedButton.Item icon={iconMinus} label="Remove" onClick={() => {}} />
</SegmentedButton.Group>
</Stack>

Dividers

Use hasDivider to render a vertical separator after the first item, splitting off the leading control from the rest of the group. This is useful when a SegmentedButton sits inline with other toolbar elements.

live

<Box
_dark={{ bgColor: 'background.primary' }}
alignItems="flex-start"
bgColor="background.primaryInvert"
borderRadius="400"
display="flex"
p="500"
>
<SegmentedButton.Group hasDivider>
<SegmentedButton.Item
icon={iconCellPhone}
label="Phone view"
onClick={() => {}}
/>
<SegmentedButton.Item icon={iconPlus} label="Zoom in" onClick={() => {}} />
<SegmentedButton.Item
icon={iconMinus}
label="Zoom out"
onClick={() => {}}
/>
<SegmentedButton.Item
icon={iconGrip}
label="Grid view"
onClick={() => {}}
/>
</SegmentedButton.Group>
</Box>

Props

SegmentedButton.Group

PropTypeDefaultDescription
childrenReactNodeSegmentedButton.Item elements
variant'primary' | 'secondary' | 'glass''primary'Sets the track background color; does not affect item styling
size'medium' | 'small' | 'xs''medium'Size applied to every item in the group
colorMode'light' | 'dark'systemForce a color mode; defaults to the surrounding theme
hasDividerbooleanfalseRender a divider after the first item (leading edge)
hasShadowbooleanfalseRender the track with a drop shadow

SegmentedButton.Item

PropTypeDefaultDescription
iconIconTypeIcon to render. When set, the item is icon-only and label is required for accessibility
labelstringAccessible label (required when icon is set)
childrenReactNodeText content for a label item (use instead of icon)
variant'primary' | 'secondary' | 'glass' | 'ghost''ghost'Per-item button style; takes precedence over the group default
onClick() => voidCalled when the item is pressed
isDisabledbooleanfalseDisables the item