Checkbox
A headless checkbox component with dual-mode support: standalone boolean binding or group multi-selection with tri-state.
Usage
The Checkbox component supports two modes:
Standalone mode: Use
v-modelonCheckbox.Rootfor simple boolean stateGroup mode: Wrap in
Checkbox.Groupfor multi-selection with array v-model
<script setup lang="ts">
import { Checkbox } from '@vuetify/v0'
</script>
<template>
<label class="inline-flex items-center gap-2">
<Checkbox.Root class="size-5 border rounded inline-flex items-center justify-center border-divider">
<Checkbox.Indicator class="text-primary text-sm">✓</Checkbox.Indicator>
</Checkbox.Root>
<span>I agree to the terms and conditions</span>
</label>
</template>
Anatomy
<script setup lang="ts">
import { Checkbox } from '@vuetify/v0'
</script>
<template>
<!-- Standalone -->
<Checkbox.Root>
<Checkbox.Indicator />
</Checkbox.Root>
<!-- Group -->
<Checkbox.Group>
<Checkbox.Root>
<Checkbox.Indicator />
</Checkbox.Root>
<Checkbox.Root>
<Checkbox.Indicator />
</Checkbox.Root>
</Checkbox.Group>
<!-- Group with Select All -->
<Checkbox.Group>
<Checkbox.SelectAll>
<Checkbox.Indicator />
</Checkbox.SelectAll>
<Checkbox.Root>
<Checkbox.Indicator />
</Checkbox.Root>
</Checkbox.Group>
<!-- With form submission -->
<Checkbox.Root>
<Checkbox.Indicator />
<Checkbox.HiddenInput />
</Checkbox.Root>
</template>Group Mode
Wrap checkboxes in Checkbox.Group for multi-selection with array-based v-model:
Selected: none
<script setup lang="ts">
import { Checkbox } from '@vuetify/v0'
import { ref } from 'vue'
const selected = ref<string[]>([])
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'cherry', label: 'Cherry' },
]
</script>
<template>
<Checkbox.Group v-model="selected" class="flex flex-col gap-2">
<label
v-for="option in options"
:key="option.value"
class="inline-flex items-center gap-2"
>
<Checkbox.Root
class="size-5 border rounded inline-flex items-center justify-center border-divider data-[state=checked]:bg-primary data-[state=checked]:border-primary"
:value="option.value"
>
<Checkbox.Indicator class="text-on-primary text-sm">✓</Checkbox.Indicator>
</Checkbox.Root>
<span>{{ option.label }}</span>
</label>
</Checkbox.Group>
<p class="mt-4 text-sm text-on-surface-variant">
Selected: {{ selected.join(', ') || 'none' }}
</p>
</template>
Accessibility
The Checkbox.Root component renders as a button and handles all ARIA attributes automatically:
role="checkbox"for proper semanticsaria-checkedreflects state (true,false, or"mixed")aria-disabledwhen checkbox is disabledaria-labelfrom thelabelproptabindex="0"for keyboard focus (removed when disabled)Space key toggles the checkbox (Enter works when rendered as button)
For custom implementations, use renderless mode and bind the attrs slot prop to your element:
<template>
<Checkbox.Root v-slot="{ attrs }" renderless>
<div v-bind="attrs">
<!-- Custom checkbox visual -->
</div>
</Checkbox.Root>
</template>Form Integration
When the name prop is provided on Checkbox.Root, a hidden native checkbox is automatically rendered for form submission:
<template>
<!-- Auto-renders hidden input for form submission -->
<Checkbox.Root name="agree" value="yes">
<Checkbox.Indicator>✓</Checkbox.Indicator>
</Checkbox.Root>
</template>For custom form integration, use Checkbox.HiddenInput explicitly:
<template>
<Checkbox.Root>
<Checkbox.Indicator>✓</Checkbox.Indicator>
<Checkbox.HiddenInput name="custom" value="override" />
</Checkbox.Root>
</template>Indeterminate State
Use Checkbox.SelectAll within a group for “select all” patterns. It automatically reflects the group’s aggregate state and toggles all items on click:
Selected: none
<script setup lang="ts">
import { Checkbox } from '@vuetify/v0'
import { ref } from 'vue'
const selected = ref<string[]>([])
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'cherry', label: 'Cherry' },
]
</script>
<template>
<Checkbox.Group v-model="selected">
<div class="flex flex-col gap-2">
<label class="inline-flex items-center gap-2 font-medium">
<Checkbox.SelectAll
class="size-5 border rounded inline-flex items-center justify-center border-divider data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary"
>
<Checkbox.Indicator v-slot="{ isMixed }" class="text-on-primary text-sm">
<span v-if="isMixed">−</span>
<span v-else>✓</span>
</Checkbox.Indicator>
</Checkbox.SelectAll>
<span>Select All</span>
</label>
<div class="ml-6 flex flex-col gap-2">
<label
v-for="option in options"
:key="option.value"
class="inline-flex items-center gap-2"
>
<Checkbox.Root
class="size-5 border rounded inline-flex items-center justify-center border-divider data-[state=checked]:bg-primary data-[state=checked]:border-primary"
:value="option.value"
>
<Checkbox.Indicator class="text-on-primary text-sm">✓</Checkbox.Indicator>
</Checkbox.Root>
<span>{{ option.label }}</span>
</label>
</div>
</div>
</Checkbox.Group>
<p class="mt-4 text-sm text-on-surface-variant">
Selected: {{ selected.join(', ') || 'none' }}
</p>
</template>
The SelectAll component:
Binds to the group’s
isAllSelectedandisMixedstateCalls
toggleAllon clickDoes NOT register as a group item
Sets
aria-checked="mixed"anddata-state="indeterminate"when partially selected
Checkbox.Root
Props
namespace
stringNamespace for context provision to children (Indicator, HiddenInput)
Default: "v0:checkbox:root"
modelValue
booleanEvents
update:model-value
[value: boolean]Slots
default
CheckboxRootSlotProps<V>Checkbox.Group
Props
mandatory
boolean | "force"Controls mandatory checkbox behavior: - false (default): No mandatory enforcement - true: Prevents deselecting the last selected item - `force`: Automatically selects the first non-disabled item on registration
Default: false
modelValue
T | T[]Events
update:model-value
[value: T | T[]]Slots
default
CheckboxGroupSlotPropsCheckbox.HiddenInput
Props
namespace
stringNamespace for context injection from parent Checkbox.Root
Default: "v0:checkbox:root"
Checkbox.Indicator
Props
namespace
stringNamespace for context injection from parent Checkbox.Root
Default: "v0:checkbox:root"
Slots
default
CheckboxIndicatorSlotPropsCheckbox.SelectAll
Props
Slots
default
CheckboxSelectAllSlotProps