Checkbox
Headless Checkbox; covers shadcn/ui Checkbox, Reka UI Checkbox, React Aria Checkbox.
| Package | @vizejs/ui/checkbox |
| Maturity | stable |
| Own the source | vize lib pull checkbox |
| Requires | controllable-state |
| Aliases | checkbox control, mixed checkbox |
| Covers | shadcn/ui Checkbox, Reka UI Checkbox, React Aria Checkbox |
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 { Checkbox } from "@vizejs/ui/checkbox";
Or copy the source into your project with vize lib pull checkbox (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
<!-- Native checkbox bound with v-model and labelled through a matching label element. -->
<script setup lang="ts">
import { ref, useId } from "vue";
import { Checkbox } from "@vizejs/ui/checkbox";
const accepted = ref(false);
const checkboxId = useId();
</script>
<template>
<form>
<Checkbox :id="checkboxId" v-model="accepted" name="terms" />
<label :for="checkboxId">I agree to the terms of service</label>
<button type="submit" :disabled="!accepted">Create account</button>
</form>
</template>
API
Checkbox
Source: src/families/selection/checkbox/checkbox-control.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue |
boolean |
undefined |
Controlled checked value. undefined selects uncontrolled behavior. |
defaultChecked |
boolean |
false |
Initial unchecked or checked state for uncontrolled use. |
indeterminate |
boolean |
false |
Render and announce a mixed checked state. |
disabled |
boolean |
false |
Disable interaction and native form submission. |
ariaLabel |
string |
undefined |
Accessible name when no associated label supplies one. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue |
[value: boolean] |
Fired when the checked state requests a new controlled boolean value. |
update:indeterminate |
[value: boolean] |
Fired when user interaction emits the next mixed-state boolean. |
change |
[value: boolean, nativeEvent: Event] |
Fired after the native checkbox change event is processed with the next checked boolean and native Event. |
Exposed
| Member | Type | Description |
|---|---|---|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
checked |
— | |
focus |
— | |
reset |
— | |
setChecked |
— |
Behavior
Normative state × input → outcome table for checkbox-control.vue (@vizejs/ui/checkbox).
Every row is proven by the named mounted-DOM test in src/families/selection/checkbox/checkbox.test.ts; a row
without a passing test is a contract violation.
| # | State | Input | Outcome | Proven by |
|---|---|---|---|---|
| C1 | any | render | native input[type=checkbox], accessible name from ariaLabel |
renders a native checkbox with an accessible name and focus control |
| C2 | any | exposed focus() |
input receives focus | renders a native checkbox with an accessible name and focus control |
| C3 | unchecked | render | aria-checked="false", data-state="unchecked" |
reports aria-checked across unchecked, checked, and mixed states |
| C4 | checked | render | aria-checked="true", data-state="checked" |
reports aria-checked across unchecked, checked, and mixed states |
| C5 | indeterminate | render | aria-checked="mixed", data-state="indeterminate", native .indeterminate |
reports aria-checked across unchecked, checked, and mixed states |
| C6 | uncontrolled | pointer click | toggles; emits update:modelValue then change, in that order |
toggles with a pointer click and emits model before change |
| C7 | uncontrolled | Space | toggles exactly once like a native checkbox | toggles with Space like a native checkbox |
| C8 | wrapped in <label> |
click on the label | toggles the checkbox (label association) | clicking the associated label toggles the checkbox |
| C9 | controlled | pointer click | emits the request; the rendered state reverts to the prop value | controlled: the parent-provided value always wins |
| C10 | controlled | prop update | rendered state follows modelValue |
controlled: the parent-provided value always wins |
| C11 | uncontrolled, seeded | render | defaultChecked seeds the initial state |
uncontrolled: defaultChecked seeds state and reset restores it |
| C12 | uncontrolled, seeded | exposed reset() |
restores the default state | uncontrolled: defaultChecked seeds state and reset restores it |
| C13 | indeterminate | pointer click | emits update:indeterminate false and change true |
indeterminate announces mixed and requests clearing on toggle |
| C14 | disabled | click / Space | no toggle, no change |
disabled checkbox ignores pointer and keyboard activation |
| C15 | disabled | Tab | skipped by the tab order | disabled checkbox ignores pointer and keyboard activation |
Mixed-state precedence (indeterminate wins over checked) is additionally
pinned as pure logic by gives the mixed visual state precedence.