A segmented control is a mutually exclusive, single-select control where all options are visible at once. Only one item can be selected at a time, and there is always one item selected. It is commonly used to switch between different views or formats of the same content — such as toggling between grid and list view, or filtering between "All", "Favorites", and "Recent".
Each dt-segmented-control-item wraps a DtButton internally and inherits its slot and prop surface, including #startIcon, #endIcon, #leading, #trailing, disabled, and label-class.
| Segmented Control | Tabs | |
|---|---|---|
| Purpose | Switch between views or formats of the same content | Navigate between distinct content sections |
| Content relationship | Same data, different presentation (e.g., grid vs. list) | Different data in each section (the filing cabinet metaphor — each tab holds different papers) |
| Hierarchy | Lower-level, often within a tabbed section | Top-level content organization |
| ARIA role | radiogroup with radio items | tablist with tab items and associated tabpanels |
| Content panel | None — consumers manage their own view switching | Built-in panel association via aria-controls |
aria-label on the segmented control that describes the purpose of the group.label prop on icon-only items for accessibility.<dt-segmented-control v-model="selected" aria-label="View filter"> <dt-segmented-control-item value="all">All</dt-segmented-control-item> <dt-segmented-control-item value="favorites">Favorites</dt-segmented-control-item> <dt-segmented-control-item value="recent">Recent</dt-segmented-control-item> <dt-segmented-control-item value="groups">Groups</dt-segmented-control-item> </dt-segmented-control>
Remove the border and padding from the container.
<dt-segmented-control v-model="selected" borderless> ... </dt-segmented-control>
<dt-segmented-control v-model="selected" :show-divider="false"> ... </dt-segmented-control>
Items share space equally. Only applies in horizontal orientation.
<dt-segmented-control v-model="selected" spread="evenly"> ... </dt-segmented-control>
Add disabled to the group to disable all items.
<dt-segmented-control v-model="selected" disabled> ... </dt-segmented-control>
Add disabled to an individual item.
<dt-segmented-control v-model="selected" aria-label="Individual disabled example"> <dt-segmented-control-item value="all">All</dt-segmented-control-item> <dt-segmented-control-item value="favorites" disabled>Favorites</dt-segmented-control-item> <dt-segmented-control-item value="recent">Recent</dt-segmented-control-item> <dt-segmented-control-item value="groups">Groups</dt-segmented-control-item> </dt-segmented-control>
<dt-segmented-control v-model="selected" :size="100|200|300|400|500"> ... </dt-segmented-control>
Use the #startIcon or #endIcon slot on dt-segmented-control-item to add an icon. The slot provides iconSize to match the control's size.
<dt-segmented-control v-model="iconSelected" aria-label="List spacing"> <dt-segmented-control-item value="compact"> <template #startIcon="{ iconSize }"> <dt-icon name="list-spacing-compact" :size="iconSize" /> </template> Compact </dt-segmented-control-item> <dt-segmented-control-item value="regular"> <template #startIcon="{ iconSize }"> <dt-icon name="list-spacing-regular" :size="iconSize" /> </template> Regular </dt-segmented-control-item> <dt-segmented-control-item value="expanded"> <template #startIcon="{ iconSize }"> <dt-icon name="list-spacing-expanded" :size="iconSize" /> </template> Expanded </dt-segmented-control-item> </dt-segmented-control>
Omit the default slot text to create icon-only items. Use the label prop for accessibility.
<div class="d-w-750"> <dt-segmented-control v-model="iconOnlySelected" aria-label="Appearance mode"> <dt-segmented-control-item value="system" label="System"> <template #startIcon="{ iconSize }"> <dt-icon name="laptop-2" :size="iconSize" /> </template> </dt-segmented-control-item> <dt-segmented-control-item value="light" label="Light"> <template #startIcon="{ iconSize }"> <dt-icon name="sun" :size="iconSize" /> </template> </dt-segmented-control-item> <dt-segmented-control-item value="dark" label="Dark"> <template #startIcon="{ iconSize }"> <dt-icon name="moon" :size="iconSize" /> </template> </dt-segmented-control-item> </dt-segmented-control> </div> <div> <dt-segmented-control v-model="iconOnlySelected" aria-label="Appearance mode" class="d-d-inline-flex"> <dt-segmented-control-item value="system" label="System"> <template #startIcon="{ iconSize }"> <dt-icon name="laptop-2" :size="iconSize" /> </template> </dt-segmented-control-item> <dt-segmented-control-item value="light" label="Light"> <template #startIcon="{ iconSize }"> <dt-icon name="sun" :size="iconSize" /> </template> </dt-segmented-control-item> <dt-segmented-control-item value="dark" label="Dark"> <template #startIcon="{ iconSize }"> <dt-icon name="moon" :size="iconSize" /> </template> </dt-segmented-control-item> </dt-segmented-control> </div>
Use the #leading and #trailing slots on dt-segmented-control-item to render content alongside labels, such as badges or count indicators.
<dt-segmented-control v-model="trailingSelected" aria-label="Fruit counts"> <dt-segmented-control-item value="apples" trailingClass="d-pie-100"> Apples <template #trailing> <dt-badge kind="count">24</dt-badge> </template> </dt-segmented-control-item> <dt-segmented-control-item value="oranges" trailingClass="d-pie-100"> Oranges <template #trailing> <dt-badge kind="count">8</dt-badge> </template> </dt-segmented-control-item> <dt-segmented-control-item value="bananas" trailingClass="d-pie-100"> Bananas <template #trailing> <dt-badge kind="count">15</dt-badge> </template> </dt-segmented-control-item> </dt-segmented-control>
Set orientation="vertical" to stack items vertically.
<dt-segmented-control v-model="selected" orientation="vertical"> ... </dt-segmented-control>
By default, items select immediately on focus via arrow keys, following the WAI-ARIA Radio Group pattern. Set activation-mode="manual" to require an explicit Enter or Space keypress after focusing an item.
<dt-segmented-control v-model="selected" activation-mode="manual"> ... </dt-segmented-control>
The segmented control implements the WAI-ARIA Radio Group pattern with roving tabindex for keyboard navigation.
Item
|
Applies to
|
Description
|
|---|
import { DtSegmentedControl, DtSegmentedControlItem } from '@dialpad/dialtone-vue';
Name
|
Type
|
|---|---|
default | DtSegmentedControlItem children |
Name
|
Default
|
Type
|
|---|---|---|
modelValue
required
| string The currently selected value (v-model). | |
activationMode | SEGMENTED_CONTROL_ACTIVATION_MODE_DEFAULT |
"auto"
|
"manual"
Controls whether items are selected on focus (auto) or on click/Space/Enter (manual). |
ariaLabel | string Accessible label for the radiogroup. | |
borderless | false | boolean Removes the border and padding from the container. |
disabled | false | boolean Disables all items in the group.
Per-item disabled is set via the disabled prop on DtSegmentedControlItem. |
id | generated unique ID | string Element ID for the radiogroup container.
Auto-generated if not provided. |
labelClass | '' | string|array|object Default label class for all items. Items can override with their own labelClass prop. |
orientation | SEGMENTED_CONTROL_ORIENTATION_DEFAULT |
"horizontal"
|
"vertical"
Orientation of the segmented control.
Maps to DtStack direction: horizontal -> row, vertical -> column. |
showDivider | true | boolean Shows the dividers between items. |
showIndicatorTransition | true |
"true"
|
"false"
If true, the selection indicator animates between items on click. |
size | SEGMENTED_CONTROL_SIZE_DEFAULT |
"100"
|
"200"
|
"300"
|
"400"
|
"500"
DtButton size for all items. Inherited by children via provide. |
spread | SEGMENTED_CONTROL_SPREAD_DEFAULT |
"grow"
|
"evenly"
Controls how items distribute space.
'grow' (default): items size to their content.
'evenly': items share space equally. |
Name
|
Type
|
|---|---|
before-change | Event Emitted before a selection change. Call event.preventDefault() to cancel the change. |
change | String Emitted when the user selects an item (click, Enter, Space, or arrow in auto mode).
Not emitted for programmatic modelValue changes. |
update:modelValue | String v-model event. Emitted when the selected value changes. |
Name
|
Type
|
|---|---|
default | Label text content |
endIcon | Icon displayed at the inline-end of the label. Provides { iconSize } scoped binding. |
leading | Content rendered before the label (e.g. badges, indicators). |
startIcon | Icon displayed at the inline-start of the label. Provides { iconSize } scoped binding. |
trailing | Content rendered after the label (e.g. badges, counts). |
Name
|
Default
|
Type
|
|---|---|---|
value
required
| string Unique value for this item, used for selection matching with v-model. | |
disabled | false | boolean Disables this individual item. |
label | string Accessible label for the button (aria-label).
Visible text comes from the default slot, not this prop.
Required for icon-only items. | |
labelClass | string|array|object Custom class for this item's label container.
Overrides the parent's labelClass when provided. |
Name
|
Type
|
|---|---|
click | PointerEvent | KeyboardEvent Native button click event. |
focus | FocusEvent Native button focus event. |
Class
|
Applies to
|
Description
|
|---|
Segmented Control documentation last updated Friday, September 4, 2026
fix/popover-modal-zindex-scope