Toggle Group
Shares one pressed state between a row of toggles, one at a time or several.
Toggle Group puts a set of Toggle.Root buttons under
one value, so pressing one can unpress the others. Useful for a choice with a
handful of options that all fit on screen, like text alignment, and for a row
of formatting buttons where several can be on at once.
<template>
<div class="flex flex-col items-start gap-4">
<Toggle.Group v-model="alignment" aria-label="Text alignment" :class="group">
<Toggle.Root
v-for="entry in alignments"
:key="entry.value"
:class="toggle"
:value="entry.value"
>
{{ entry.label }}
</Toggle.Root>
</Toggle.Group>
<Toggle.Group
v-model="formats"
aria-label="Formatting"
:class="group"
:options="{ mode: 'multiple' }"
>
<Toggle.Root
v-for="entry in formatting"
:key="entry.value"
:aria-label="entry.label"
:class="[toggle, entry.glyphClass]"
:value="entry.value"
>
{{ entry.glyph }}
</Toggle.Root>
</Toggle.Group>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { Toggle } from '@maas/mirror/vue/Toggle'
const alignment = ref(['left'])
const formats = ref(['bold'])
const alignments = [
{ value: 'left', label: 'Left' },
{ value: 'center', label: 'Center' },
{ value: 'right', label: 'Right' },
]
const formatting = [
{ value: 'bold', label: 'Bold', glyph: 'B', glyphClass: 'font-bold' },
{ value: 'italic', label: 'Italic', glyph: 'I', glyphClass: 'italic' },
{
value: 'underline',
label: 'Underline',
glyph: 'U',
glyphClass: 'underline',
},
]
const group =
'rounded-[calc(var(--radius-component-md)+0.25rem+1px)] border-surface flex gap-1 border p-1'
const toggle = [
'inline-flex h-9 min-w-9 items-center justify-center px-3',
'rounded-component-md border-2 border-[transparent] type-component-sm',
'text-primary-solid transition-all duration-100 ease-linear',
'outline-4 outline-transparent focus-visible:focus-ring',
'hover:bg-primary-subtle',
'active:bg-primary-subtle-active',
'data-[state=on]:bg-primary-solid data-[state=on]:text-primary-on-solid',
'data-[state=on]:hover:bg-primary-solid-hover',
'data-[state=on]:active:bg-primary-solid-active',
].join(' ')
</script>
Usage guidelines
- Every
Toggle.Rootinside a group needs avalue, since that is how the group tells one from another. A toggle without one throws rather than joining the group silently.must - The group is one tab stop and has no name of its own, so give it an
aria-labeldescribing what the toggles have in common.must - Where only one option can be on and one always has to be, use
Radioinstead. A single-select group can be emptied by pressing the toggle that is already on, which a radio group cannot.should