Segmented Control
A segmented control presents a linear set of selectable segments, supporting both single- and multi-select interactions. It offers immediate visual feedback and maintains coherence across related options.
import {SegmentedControl} from "@qualcomm-ui/react/segmented-control"Usage
The SegmentedControl component allows users to make a selection from multiple options, exclusive (similar to radio buttons) or not (similar to checkboxes).
It is typically used for filtering content, sorting elements or switching between views within the same context.
Examples
Simple
Use the simple API to create segmented control items using minimal markup.
<SegmentedControl.Root defaultValue={["chart"]}>
<SegmentedControl.Item text="Chart" value="chart" />
<SegmentedControl.Item text="Table" value="table" />
<SegmentedControl.Item text="Map" value="map" />
</SegmentedControl.Root>
Composite
Build with the composite API for granular control. This API requires you to provide each subcomponent, but gives you full control over the structure and layout.
<SegmentedControl.Root defaultValue={["chart"]}>
<SegmentedControl.ItemRoot value="chart">
<SegmentedControl.ItemText>Chart</SegmentedControl.ItemText>
<SegmentedControl.HiddenInput />
</SegmentedControl.ItemRoot>
<SegmentedControl.ItemRoot value="table">
<SegmentedControl.ItemText>Table</SegmentedControl.ItemText>
<SegmentedControl.HiddenInput />
</SegmentedControl.ItemRoot>
<SegmentedControl.ItemRoot value="map">
<SegmentedControl.ItemText>Map</SegmentedControl.ItemText>
<SegmentedControl.HiddenInput />
</SegmentedControl.ItemRoot>
</SegmentedControl.Root>
Multiple
By default, a segmented control allows for a single selection. Use the multiple prop to create a segmented control that allows for multiple selections.
<SegmentedControl.Root multiple>
<SegmentedControl.Item text="Production" value="prod" />
<SegmentedControl.Item text="Staging" value="staging" />
<SegmentedControl.Item text="Development" value="dev" />
<SegmentedControl.Item text="QA" value="qa" />
</SegmentedControl.Root>
Orientation
Use the orientation prop to control the layout direction of the SegmentedControl. Options include:
horizontal: Items are laid out in a row (default).vertical: Items are laid out in a column.
<SegmentedControl.Root defaultValue={["chart"]} orientation="vertical">
<SegmentedControl.Item text="Chart" value="chart" />
<SegmentedControl.Item text="Table" value="table" />
<SegmentedControl.Item text="Map" value="map" />
</SegmentedControl.Root>
Icon
Use the icon prop on the SegmentedControl.Item or SegmentedControl.ItemRoot components to add icons to the segmented control items.
<SegmentedControl.Root defaultValue={["chart"]}>
<SegmentedControl.Item icon={ChartArea} text="Chart" value="chart" />
<SegmentedControl.Item icon={Table} text="Table" value="table" />
<SegmentedControl.Item icon={Map} text="Map" value="map" />
</SegmentedControl.Root>
Layout
Use the layout prop to control how the SegmentedControl is sized and aligned within its container. Options include:
hug: Content-sized; width matches the items only (default).fill: Full width; items share space evenly.
{(["hug", "fill"] as QdsSegmentedControlLayout[]).map((layout) => (
<SegmentedControl.Root
key={layout}
defaultValue={["chart"]}
layout={layout}
>
<SegmentedControl.Item text="Chart" value="chart" />
<SegmentedControl.Item text="Table" value="table" />
<SegmentedControl.Item text="Map" value="map" />
</SegmentedControl.Root>
))}
Size
Use the size prop to control the size of the segmented control. The available sizes are sm, md (default), and lg.
{(["sm", "md", "lg"] as QdsSegmentedControlSize[]).map((size) => (
<SegmentedControl.Root key={size} defaultValue={["chart"]} size={size}>
<SegmentedControl.Item text="Chart" value="chart" />
<SegmentedControl.Item text="Table" value="table" />
<SegmentedControl.Item text="Map" value="map" />
</SegmentedControl.Root>
))}
Variant
Use the variant prop to control the visual style of the segmented control. The available variants are primary (default) and neutral.
{(["primary", "neutral"] as QdsSegmentedControlVariant[]).map(
(variant) => (
<SegmentedControl.Root
key={variant}
defaultValue={["chart"]}
variant={variant}
>
<SegmentedControl.Item text="Chart" value="chart" />
<SegmentedControl.Item text="Table" value="table" />
<SegmentedControl.Item text="Map" value="map" />
</SegmentedControl.Root>
),
)}
Disabled
Use the segmented control's disabled prop to control the disabled state of the entire control. Use the segmented control item's disabled prop to control the disabled state of individual items.
<SegmentedControl.Root disabled>
<SegmentedControl.Item text="Chart" value="chart" />
<SegmentedControl.Item text="Table" value="table" />
<SegmentedControl.Item text="Map" value="map" />
</SegmentedControl.Root>
Controlled state
Use the value prop to control the selected value of the segmented control. This allows for more complex interactions and integration with form libraries.
<SegmentedControl.Root
multiple
onValueChange={(values) => {
console.log(`Selected values: ${values?.length ? values : "<none>"}`)
setValue(values)
}}
value={value}
>
<SegmentedControl.Item text="Production" value="prod" />
<SegmentedControl.Item text="Staging" value="staging" />
<SegmentedControl.Item text="Development" value="dev" />
<SegmentedControl.Item text="QA" value="qa" />
</SegmentedControl.Root>
Accessibility
Keyboard Navigation
Users can navigate the segmented control using the keyboard. The following keys are supported:
Tab/Shift + Tab: Move focus between items.Space/Enter: Select the focused item. Unselects an already selected item if multiple is set.
Icon only
While it is possible to use icon-only items in the segmented control, it is important to ensure that they are easily understood and accessible.
Pick meaningful icons and use the aria-label attribute to describe their purpose.
<SegmentedControl.Root defaultValue={["chart"]}>
<SegmentedControl.Item
aria-label="Chart view"
icon={ChartArea}
value="chart"
/>
<SegmentedControl.Item
aria-label="Table view"
icon={Table}
value="table"
/>
<SegmentedControl.Item aria-label="Map view" icon={Map} value="map" />
</SegmentedControl.Root>
API
<SegmentedControl.Root>
| Prop | Type | Default |
|---|---|---|
The initial value of the group when rendered.
Use when you don't need to control the value of the group. | string[] | |
The document's text/writing direction. | 'ltr' | 'rtl' | 'ltr' |
Whether the group is disabled. When true, prevents user interaction and
applies visual styling to indicate the disabled state. | boolean | |
The layout used to display the segmented control. - hug: Content-sized; width matches the items only (default).- fill: Full width; items share space evenly. | 'hug' | 'fill' | 'hug' |
Whether the control allows multiple selections or not. | boolean | |
Function called when the value of the segmented control group changes. | ( | |
Orientation of the segmented control group. | | 'horizontal' | 'horizontal' |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement | |
The size of the segmented control. | | 'sm' | 'md' |
The controlled value of the group. | string[] | |
The variant of the segmented control. | | 'primary' | undefined |
string[]
'ltr' | 'rtl'
boolean'hug' | 'fill'
-
hug: Content-sized; width matches the items only (default).-
fill: Full width; items share space evenly.boolean(
value: string[],
) => void
| 'horizontal'
| 'vertical'
| ReactElement
| ((
props: object,
) => ReactElement)
| 'sm'
| 'md'
| 'lg'
string[]
| 'primary'
| 'neutral'
| Attribute / Property | Value |
|---|---|
className | 'qui-segmented-control__root' |
data-disabled | |
data-layout | 'hug' | 'fill' |
data-orientation | | 'horizontal' |
data-part | 'group' |
data-scope | 'segmented-control' |
data-size | | 'sm' |
data-variant | | 'primary' |
className'qui-segmented-control__root'data-disableddata-layout'hug' | 'fill'
data-orientation| 'horizontal'
| 'vertical'
data-part'group'data-scope'segmented-control'data-size| 'sm'
| 'md'
| 'lg'
data-variant| 'primary'
| 'neutral'
<SegmentedControl.Item>
The SegmentedControl.Item extends the SegmentedControl.ItemRoot with the following props:
Composite API
<SegmentedControl.ItemRoot>
<label> by default.| Prop | Type |
|---|---|
The value of the item. | string |
Whether the item is disabled. | boolean |
Icon, positioned before the item label if there is one. | | LucideIcon |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
stringboolean| LucideIcon
| ReactNode
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-segmented-control__item' |
data-active | |
data-disabled | |
data-focus | |
data-focus-visible | |
data-hover | |
data-invalid | |
data-part | 'root' |
data-readonly | |
data-scope | 'checkbox' |
data-state | | 'checked' |
className'qui-segmented-control__item'data-activedata-disableddata-focusdata-focus-visibledata-hoverdata-invaliddata-part'root'data-readonlydata-scope'checkbox'data-state| 'checked'
| 'indeterminate'
| 'unchecked'
<SegmentedControl.ItemText>
<span> by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-segmented-control__item-text' |
data-active | |
data-disabled | |
data-focus | |
data-focus-visible | |
data-hover | |
data-invalid | |
data-part | 'label' |
data-readonly | |
data-scope | 'checkbox' |
data-state | | 'checked' |
className'qui-segmented-control__item-text'data-activedata-disableddata-focusdata-focus-visibledata-hoverdata-invaliddata-part'label'data-readonlydata-scope'checkbox'data-state| 'checked'
| 'indeterminate'
| 'unchecked'
<SegmentedControl.HiddenInput>
<input type=radio> by
default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-segmented-control__item-hidden-input' |
data-active | |
data-disabled | |
data-focus | |
data-focus-visible | |
data-hover | |
data-invalid | |
data-part | 'hidden-input' |
data-readonly | |
data-scope | 'checkbox' |
data-state | | 'checked' |
style |
className'qui-segmented-control__item-hidden-input'data-activedata-disableddata-focusdata-focus-visibledata-hoverdata-invaliddata-part'hidden-input'data-readonlydata-scope'checkbox'data-state| 'checked'
| 'indeterminate'
| 'unchecked'
style
<fieldset>by default.