Toggle Group
Accessible, unstyled toggle button group with single or multiple selection.
|
|
| Package |
@vizejs/ui/toggle-group |
| Maturity |
stable |
| Own the source |
vize lib pull toggle-group |
| Requires |
context, controllable-state |
| Aliases |
toggle button group, pressed button group, segmented control |
| Covers |
WAI-ARIA toggle button group, Radix UI ToggleGroup, Reka UI ToggleGroup |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { ToggleGroup, ToggleGroupItem } from "@vizejs/ui/toggle-group";
Or copy the source into your project with vize lib pull toggle-group (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- Multiple-selection formatting toggle group bound with v-model. -->
<script setup lang="ts">
import { computed, ref } from "vue";
import { ToggleGroup, ToggleGroupItem } from "@vizejs/ui/toggle-group";
import type { ToggleGroupValue } from "@vizejs/ui/toggle-group";
const formatting = ref<ToggleGroupValue>(["bold"]);
const summary = computed(() =>
Array.isArray(formatting.value) && formatting.value.length > 0
? formatting.value.join(", ")
: "none",
);
</script>
<template>
<div>
<ToggleGroup v-model="formatting" type="multiple" aria-label="Text formatting">
<ToggleGroupItem value="bold">Bold</ToggleGroupItem>
<ToggleGroupItem value="italic">Italic</ToggleGroupItem>
<ToggleGroupItem value="underline">Underline</ToggleGroupItem>
</ToggleGroup>
<output>Active: {{ summary }}</output>
</div>
</template>
API
ToggleGroup
Source: src/families/selection/toggle-group/toggle-group.vue
Props
| Prop |
Type |
Default |
Description |
as |
PrimitiveAs |
"div" |
Native element, custom element, or component to render. |
type |
ToggleGroupType |
"single" |
Selection mode for item activation. |
modelValue |
ToggleGroupValue |
undefined |
Controlled selected value. undefined selects uncontrolled behavior. |
defaultValue |
ToggleGroupValue |
undefined |
Initial value for uncontrolled use and the value restored by reset. |
disabled |
boolean |
false |
Disable every item and remove the group from roving focus. |
orientation |
ToggleGroupOrientation |
"horizontal" |
Directional layout hint used by arrow-key roving focus. |
loop |
boolean |
true |
Whether arrow-key navigation wraps at the first and last enabled item. |
rovingFocus |
boolean |
true |
Whether items participate in a single-tabstop roving focus model. |
ariaLabel |
string |
undefined |
Accessible name when no visible label or aria-labelledby supplies one. |
ariaLabelledby |
string |
undefined |
Space-separated ids that label the group. |
ariaDescribedby |
string |
undefined |
Space-separated ids that describe the group. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: ToggleGroupValue] |
Fired when the selected value requests a new controlled value. |
change |
[value: ToggleGroupValue, previous: ToggleGroupValue, nativeEvent: MouseEvent] |
Fired after user activation requests a distinct group value. |
Slots
| Slot |
Slot props |
Description |
default |
ToggleGroupSlotState |
Compound ToggleGroup items. Receives normalized selection and navigation state. |
Exposed
| Member |
Type |
Description |
value |
ToggleGroupValue |
Current selected value: a string, an array for multiple mode, or null for no single selection. |
pressedValues |
readonly string[] |
Current pressed values normalized to an immutable array. |
disabled |
boolean |
Whether the group suppresses every item activation. |
type |
ToggleGroupType |
Selection mode used by item activation. |
orientation |
ToggleGroupOrientation |
Directional layout hint used by roving focus. |
state |
ToggleGroupState |
Stable state token for styling and tests. |
element |
PrimitiveElement | null |
Rendered root element or component instance. |
focus |
(options?: FocusOptions) => void |
Move focus to the active, selected, or first enabled item. |
setValue |
(value: ToggleGroupValue) => boolean |
Request a group value update and report whether it differs. |
toggleValue |
(value: string, pressed?: boolean) => boolean |
Toggle one item value programmatically and report whether it differs. |
reset |
() => boolean |
Restore the current default value and report whether it changed. |
ToggleGroupItem
Source: src/families/selection/toggle-group/toggle-group-item.vue
Props
| Prop |
Type |
Default |
Description |
as |
PrimitiveAs |
"button" |
Native element, custom element, or component to render. |
native |
boolean |
auto |
Whether the rendered target already implements native button semantics. |
type |
"button" | "reset" | "submit" |
"button" |
Native button submission behavior. |
value (required) |
string |
required |
Item value used by the group selection model. |
disabled |
boolean |
false |
Disable this item while preserving the rest of the group. |
ariaLabel |
string |
undefined |
Accessible name when no visible label or aria-labelledby supplies one. |
ariaLabelledby |
string |
undefined |
Space-separated ids that label this item. |
ariaDescribedby |
string |
undefined |
Space-separated ids that describe this item. |
Events
| Event |
Payload |
Description |
press |
[value: string, pressed: boolean, nativeEvent: MouseEvent] |
Fired after user activation requests this item to toggle. |
Slots
| Slot |
Slot props |
Description |
default |
ToggleGroupItemSlotState |
Renders item contents with current pressed and availability state. |
Exposed
| Member |
Type |
Description |
value |
string |
Item value used by the group selection model. |
pressed |
boolean |
Whether this item is pressed by the group. |
disabled |
boolean |
Whether this item or its group suppresses activation. |
orientation |
ToggleGroupOrientation |
Directional layout hint inherited from the group. |
state |
ToggleGroupItemState |
Stable state token for styling and tests. |
element |
PrimitiveElement | null |
Rendered item element or component instance. |
focus |
(options?: FocusOptions) => void |
Move focus to the rendered item. |
Behavior
Normative contract for toggle-group.vue and toggle-group-item.vue (@vizejs/ui/toggle-group).
Every row is proven by the named mounted-DOM, SSR, type, renderer, size, and tree-shaking gates.
| ID |
State |
Input |
Outcome |
Evidence |
| G1 |
single, empty |
render |
root renders role="group" and horizontal data hooks; items render native buttons with pressed state |
renders grouped toggle button semantics |
| G2 |
uncontrolled single |
item click |
pressing an unpressed item selects its value; pressing it again clears the single value |
uncontrolled single mode toggles one value and emits changes |
| G3 |
controlled single |
item click |
emits the requested next value while DOM state stays controlled until the parent accepts it |
controlled single value wins until the parent accepts the request |
| G4 |
uncontrolled multiple |
item click |
pressed values are appended and removed as an immutable array without duplicates |
multiple mode adds and removes item values |
| G5 |
roving horizontal/vertical |
Arrow/Home/End keydown |
focus moves through enabled items, respects orientation, skips disabled items, and honors loop |
roving focus follows orientation and skips disabled items |
| G6 |
disabled group or item |
click or keyboard |
activation is suppressed; native buttons receive disabled, custom hosts receive aria-disabled |
disabled groups and items suppress activation |
| G7 |
item without provider |
setup |
item setup throws the shared missing-context diagnostic |
items require a matching group provider |
| G8 |
SSR and hydration |
isolated requests |
renders byte-identical markup and hydrates without diagnostics or node replacement |
src/families/selection/toggle-group/toggle-group-ssr.test.ts |
| G9 |
DOM/SSR/Vapor |
compile |
authored root, item, and consumer SFCs compile in every renderer lane without fallback |
scripts/check-renderers.ts |
| G10 |
root/subpath consumer bundle |
production build |
root and subpath imports retain only the toggle-group contract, emit no CSS, and stay in budget |
scripts/check-tree-shaking.mjs |
| Surface |
Contract |
Default |
type |
"single" | "multiple" controls item toggle behavior |
"single" |
modelValue |
string | readonly string[] | null; undefined selects uncontrolled use |
undefined |
defaultValue |
initial uncontrolled value normalized by type |
null or [] |
orientation |
"horizontal" | "vertical" exposed to data hooks and arrow navigation |
"horizontal" |
loop |
wraps roving focus at the first and last enabled item |
true |
rovingFocus |
keeps enabled items in a single-tabstop focus model |
true |
item value |
string membership key for pressed state |
required |
data-vize-ui |
"toggle-group" on root and "toggle-group-item" on items |
always |
item aria-pressed |
"true" while the item value is selected, otherwise "false" |
always |