Beta, expect API change, and bugs. Hit one? Tell us.

Skip to content

Checkbox

A tri-state checkable control.

<script setup lang="ts">
import { Checkbox } from '@shardsui/vue/checkbox'
</script>

<template>
  <label class="flex items-center gap-2 text-sm font-normal text-gray-900">
    <Checkbox.Root
      checked
      class="flex size-4 shrink-0 items-center justify-center rounded-xs focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-950 data-checked:bg-gray-900 data-unchecked:border data-unchecked:border-gray-300"
    >
      <Checkbox.Indicator class="flex text-gray-50 data-unchecked:hidden">
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="size-4">
          <path
            d="M6 14.15L10.0321 18L18 7"
            stroke="currentColor"
            stroke-width="1.5"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
        </svg>
      </Checkbox.Indicator>
    </Checkbox.Root>
    Remind me to practice daily
  </label>
</template>

Anatomy

<script setup>
import { Checkbox } from '@shardsui/vue/checkbox'
</script>

<template>
  <Checkbox.Root>
    <Checkbox.Indicator />
  </Checkbox.Root>
</template>

Usage guidelines

  • Form controls must have an accessible name: give the checkbox one by wrapping it in a <label>, or with aria-label / aria-labelledby.

Examples

Labeling a checkbox

The simplest way to name a checkbox is to wrap it in a <label>:

<template>
  <label>
    <Checkbox.Root>
      <Checkbox.Indicator>
        <!-- checkmark icon -->
      </Checkbox.Indicator>
    </Checkbox.Root>
    Accept terms and conditions
  </label>
</template>

Checkbox.Root renders a <span> by default so the wrapping <label> toggles the hidden <input type="checkbox"> natively.

Rendering as a native button

When you point a separate label at the checkbox with for/id instead of wrapping it, render it as a native button with as="button":

<template>
  <div>
    <label for="notifications-checkbox">Enable notifications</label>
    <Checkbox.Root id="notifications-checkbox" as="button">
      <Checkbox.Indicator />
    </Checkbox.Root>
  </div>
</template>

Form integration

Field wires the label and form association:

<template>
  <Form>
    <Field.Root name="stayLoggedIn">
      <Field.Label>
        <Checkbox.Root />
        Stay logged in for 7 days
      </Field.Label>
    </Field.Root>
  </Form>
</template>

API reference

Root

Represents the checkbox itself. Renders a <span> element and a hidden <input> beside.

PropTypeDefault
AttributeDescription
data-checkedPresent when checked (and not indeterminate).
data-uncheckedPresent when unchecked (and not indeterminate).
data-indeterminatePresent when indeterminate.
data-disabledPresent when disabled.
data-readonlyPresent when read-only.
data-requiredPresent when required.
data-validPresent when the field is valid (wrapped in Field.Root).
data-invalidPresent when the field is invalid (wrapped in Field.Root).
data-touchedPresent when the field has been touched (wrapped in Field.Root).
data-dirtyPresent when the value has changed (wrapped in Field.Root).
data-filledPresent when checked (wrapped in Field.Root).
data-focusedPresent when focused (wrapped in Field.Root).

Indicator

Indicates whether the checkbox is ticked. Renders a <span> element.

PropTypeDefault

Inherits the same data attributes as Root, plus:

AttributeDescription
data-starting-stylePresent when the indicator is animating in.
data-ending-stylePresent when the indicator is animating out.