Checkbox

3 parts

A toggleable control with checked, unchecked, and 'indeterminate' states, built on a native <button role="checkbox">. The interactive root: it owns the checked state (controlled via v-model:checked or uncontrolled via defaultChecked), handles toggling, exposes a hidden form input when name is set, and provides context to CheckboxIndicator. Use it whenever you need a styled checkbox that integrates with forms or supports a mixed/partial state. The checked value is generic: with the default trueValue/falseValue (true/false) it behaves as a boolean checkbox, but those props let the model carry arbitrary values ('yes'/'no', objects, …) compared by deep equality. Nesting the root inside a CheckboxGroupRoot switches it to group mode: its checked state derives from membership in the group's array model and toggling adds/removes its value.

Demo

Loading demo…

Anatomy

Import the parts and compose them. Each part forwards attributes to its underlying element.

vue
import {
  CheckboxGroupRoot,
  CheckboxIndicator,
  CheckboxRoot,
} from '@robonen/primitives/forms/checkbox';

<CheckboxRoot>
  <CheckboxGroupRoot />
  <CheckboxIndicator />
</CheckboxRoot>

API Reference

CheckboxGroupRoot

GroupRoot

Coordinates a set of related checkboxes behind a single array model. It owns the list of selected `value`s (`v-model` or uncontrolled `defaultValue`), applies a group-level `disabled`, optionally wires arrow-key roving focus across the children, and — when `name` is set inside a `<form>` — submits the selection through hidden inputs. Each nested `CheckboxRoot` derives its checked state from membership in this model and toggling adds/removes its `value`. Reach for it whenever several checkboxes share one logical answer (a multi-select question, a filter set, a permissions matrix).

PropTypeDescription
defaultValue?T[]Uncontrolled initial selection.
modelValue?T[]Controlled selection. Bind with v-model.
disabled?booleanDisable every checkbox in the group.
required?booleanMark the submitted group input as required.
name?stringHidden input name; serializes the selection for form submission.
rovingFocus?booleanEnable arrow-key roving focus across the checkboxes.
orientation?OrientationNavigation orientation when rovingFocus is on.
dir?DirectionWriting direction (RTL-aware navigation). Falls back to config dir.
loop?booleanWrap focus around the ends.
Emits
EventPayload
update:modelValue[value: T[] | undefined]

CheckboxIndicator

Indicator

Renders its content only when the parent `CheckboxRoot` is checked or indeterminate, mirroring that state via `data-state`. Place the check/dash icon inside it; use `forceMount` to keep it mounted for CSS exit animations.

PropTypeDescription
forceMount?booleanKeep mounted even when unchecked (for CSS exit animations).

CheckboxRoot

Root

A toggleable control with checked, unchecked, and `'indeterminate'` states, built on a native `<button role="checkbox">`. The interactive root: it owns the checked state (controlled via `v-model:checked` or uncontrolled via `defaultChecked`), handles toggling, exposes a hidden form input when `name` is set, and provides context to `CheckboxIndicator`. Use it whenever you need a styled checkbox that integrates with forms or supports a mixed/partial state. The checked value is generic: with the default `trueValue`/`falseValue` (`true`/`false`) it behaves as a boolean checkbox, but those props let the model carry arbitrary values (`'yes'`/`'no'`, objects, …) compared by deep equality. Nesting the root inside a `CheckboxGroupRoot` switches it to group mode: its checked state derives from membership in the group's array model and toggling adds/removes its `value`.

PropTypeDescription
defaultChecked?T | 'indeterminate'Uncontrolled initial checked state.
disabled?booleanDisable interaction.
required?booleanMark associated hidden input as required.
name?stringHidden input name attribute.
value?AcceptableValueValue submitted with the form (hidden input) and used for membership when inside a CheckboxGroupRoot.
id?stringId of the root element; anchors <label for> and aria-label derivation.
trueValue?TValue the model holds when checked.
falseValue?TValue the model holds when unchecked.
checked?T | 'indeterminate' | undefinedTwo-way bound value (v-model:checked).
Emits
EventPayload
update:checked[value: T | 'indeterminate' | undefined]