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.
<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.
<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.
<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
<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.
<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".
<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.
<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.
<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
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | SegmentedButton.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' | system | Force a color mode; defaults to the surrounding theme |
hasDivider | boolean | false | Render a divider after the first item (leading edge) |
hasShadow | boolean | false | Render the track with a drop shadow |
SegmentedButton.Item
| Prop | Type | Default | Description |
|---|---|---|---|
icon | IconType | Icon to render. When set, the item is icon-only and label is required for accessibility | |
label | string | Accessible label (required when icon is set) | |
children | ReactNode | Text 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 | () => void | Called when the item is pressed | |
isDisabled | boolean | false | Disables the item |
React Native
SegmentedButton.Group provides size and a default item variant via
context; SegmentedButton.Item renders as a Button or IconButton
underneath depending on whether it has an icon or children.
Common Mistakes
- Setting
variantonSegmentedButton.Grouponly styles the track background — every item still defaults toghostregardless of the group's variant. Setvarianton eachItemindividually to change how the items themselves look; the group-levelvariantwon't cascade to them. SegmentedButton.Itemmust be rendered insideSegmentedButton.Group— it warns in development and falls back to defaults (mediumsize,ghostvariant) when rendered standalone, rather than throwing.onPress, notonClick, is the real prop passed through to the underlyingButton/IconButton— same accessor-naming gotcha as elsewhere in this package.