Toggle Group
npx @vyui/cli add toggle-groupOverview
VyToggleGroup renders connected toggle buttons from an items array. It supports single or multiple selection, controlled and uncontrolled values, horizontal or vertical layout, disabled items, icons, labels, and a custom item slot.
Usage
Use type="single" with a scalar v-model. Primitive strings and numbers are normalized into matching labels and values.
<script setup lang="ts">
import { ref } from 'vue'
import { VyToggleGroup } from '@vyui/kit'
const alignment = ref('center')
const items = [
{ label: 'Left', value: 'left', icon: 'i-lucide-align-left' },
{ label: 'Center', value: 'center', icon: 'i-lucide-align-center' },
{ label: 'Right', value: 'right', icon: 'i-lucide-align-right' },
]
</script>
<template>
<VyToggleGroup v-model="alignment" :items="items" />
</template>
Multiple selection
Use an array model with type="multiple". Tapping an item adds or removes its value.
<script setup lang="ts">
import { ref } from 'vue'
import { VyToggleGroup } from '@vyui/kit'
const formatting = ref<string[]>(['bold'])
const items = [
{ label: 'Bold', value: 'bold' },
{ label: 'Italic', value: 'italic' },
{ label: 'Underline', value: 'underline', disabled: true },
]
</script>
<template>
<VyToggleGroup
v-model="formatting"
type="multiple"
:items="items"
color="secondary"
variant="soft"
/>
</template>
Custom items
The default slot replaces an entire item's built-in icon and label. It receives the normalized item, its index, and a resolved hex color for custom SVG icons.
<VyToggleGroup v-model="density" :items="items">
<template #default="{ item, iconColor }">
<VyIcon :name="item.icon" :color="iconColor" />
<text>{{ item.label }}</text>
</template>
</VyToggleGroup>
Features and behavior
singlemode stores one string or number. Tapping the selected item again clears the runtime value.multiplemode stores an array and toggles each tapped value independently.- Use
modelValueorv-modelfor controlled state, ordefaultValuefor an uncontrolled initial selection. - String and number items become
{ value: item, label: String(item) }. - Object items use
value, falling back tolabel; their label falls back toString(value). - Object items should provide at least
valueorlabel, and every resolved value should be unique because it is also used as the render key. - Group-level
disableddisables every item. An item'sdisabledfield disables only that item. orientationchanges connected-border layout; it does not reorder the supplied items.
Toggle group item
| Field | Type | Default | Description |
|---|---|---|---|
label | string | String form of the resolved value | Visible item text. |
icon | string | undefined | Leading Iconify icon name. |
value | string | number | label | Selection value and render key. |
disabled | boolean | false | Prevents interaction for this item. |
[key: string] | any | — | Additional application data retained on the normalized item and exposed to the slot. |
The items array also accepts primitive strings and numbers.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'single' | 'multiple' | 'single' | Whether one value or multiple values can be selected. |
modelValue | string | number | Array<string | number> | undefined | Controlled selection; use an array for multiple mode. |
defaultValue | string | number | Array<string | number> | Single: undefined; multiple: [] | Initial uncontrolled selection. |
items | Array<ToggleGroupItem | string | number> | undefined | Items to normalize and render. |
disabled | boolean | false | Disables every item in the group. |
color | Color | 'primary' | Semantic selected-state color. |
variant | 'outline' | 'soft' | 'subtle' | 'outline' | Item surface, border, and selected-state treatment. |
size | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Item padding, text size, gap, and icon size. |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Connected row or column layout. |
class | any | undefined | Classes merged onto the group root. |
ui | Partial<Record<ToggleGroupSlot, any>> | undefined | Per-instance theme slot overrides. |
Color defaults to primary, secondary, success, info, warning, error, or neutral, and supports consumer registry extensions.
Keep type coherent with the value shape: scalar for single, array for multiple. The kit wrapper always defaults an omitted type to single.
Emits
| Event | Payload | Description |
|---|---|---|
update:modelValue | string | number | Array<string | number> | Emitted after selection changes. In single mode, deselecting the active item produces undefined at runtime. |
Slots
| Slot | Props | Description |
|---|---|---|
default | { item, index, iconColor } | Replaces the built-in icon and label for every item. item is normalized and iconColor is a resolved hex string. |
Styling and theming
Override globally through appConfig.ui.toggleGroup or locally with ui.
| UI slot | Purpose |
|---|---|
root | Group direction, wrapping, and connected overlap. |
item | Toggle layout, spacing, borders, surfaces, rounding, and disabled state. |
leadingIcon | Built-in icon size and state-dependent foreground. |
label | Built-in label truncation and state-dependent foreground. |
The theme combines color, variant, size, and orientation.
| Variant | Appearance |
|---|---|
outline | White items with neutral borders; selected items gain a semantic border and light surface. |
soft | Neutral resting surface; selected items gain a stronger light semantic surface. |
subtle | Lighter neutral border than outline; selected items use a soft semantic border and surface. |
Horizontal groups use a wrapping row, overlap adjacent borders by one pixel, and round the first and last inline edges. Vertical groups use a column, overlap horizontal borders, round the top and bottom items, and make each item full width.
Accessibility
Each item is exposed by the core primitive as a focusable native button and announces pressed or not pressed. Disabled groups and items use the disabled trait.
The kit item shape does not currently forward an accessibility-label to individual toggle roots. Prefer visible, descriptive labels. Icon-only groups do not have a kit-level per-item labeling API today, so treat them as an accessibility limitation and test them with VoiceOver and TalkBack. The group root itself does not add a native group role, and the current accessibility layer does not bridge these semantics to web ARIA.
Platform notes
- Items respond to Lynx
tapevents through the@vyui/coretoggle primitives. - Lynx SVG does not inherit
currentColor; built-in icons receive a resolved hex color, and custom slots receive the same value asiconColor. - Text color classes are applied directly to
leadingIconandlabelbecause CSS inheritance is disabled in the Lynx build. - The default theme is light-mode-only.
Related components
Togglefor one independent pressed-state control.Radio Groupfor a required single-choice form field.Switchfor an immediately applied binary setting.