Skip to content
v1.4.2
Fit

Checkbox

A boolean control with an optional label, secondary description, and an indeterminate (mixed) state. The whole thing is a <label>, so clicking the text toggles the box.

bash
jlds add checkbox

Usage

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/checkbox.css">

<label class="jl-check">
  <input type="checkbox" class="jl-check__input" checked />
  <span class="jl-check__box">
    <svg class="jl-check__mark" viewBox="0 0 12 12" fill="none" aria-hidden="true">
      <path d="M2.5 6.2l2.2 2.3 4.8-5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
    </svg>
    <span class="jl-check__dash" aria-hidden="true"></span>
  </span>
  <span class="jl-check__body">
    <span class="jl-check__label">Email me about updates</span>
  </span>
</label>
vue
<script setup lang="ts">
import { ref } from "vue"
import { Checkbox } from "@/components/ui/checkbox"

const checked = ref(true)
</script>

<template>
  <Checkbox v-model="checked" label="Email me about updates" />
</template>
tsx
import { Checkbox } from "@/components/ui/checkbox"

<Checkbox defaultChecked label="Email me about updates" />

With description

Pass a description for a secondary line under the label.

html
<label class="jl-check">
  <input type="checkbox" class="jl-check__input" checked />
  <span class="jl-check__box">
    <svg class="jl-check__mark" viewBox="0 0 12 12" fill="none" aria-hidden="true">
      <path d="M2.5 6.2l2.2 2.3 4.8-5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
    </svg>
    <span class="jl-check__dash" aria-hidden="true"></span>
  </span>
  <span class="jl-check__body">
    <span class="jl-check__label">Enable notifications</span>
    <span class="jl-check__desc">Get notified when a deploy finishes.</span>
  </span>
</label>
vue
<template>
  <Checkbox
    v-model="checked"
    label="Enable notifications"
    description="Get notified when a deploy finishes."
  />
</template>
tsx
<Checkbox
  defaultChecked
  label="Enable notifications"
  description="Get notified when a deploy finishes."
/>

Indeterminate, invalid & disabled

indeterminate renders the mixed dash — useful for a "select all" parent. It's a DOM property, so it's set by the component (React/Vue) rather than markup. invalid shows error styling on the box (parity with Input/Textarea/Combobox); add disabled to dim and lock.

html
<!-- indeterminate is a JS property: el.indeterminate = true -->
<label class="jl-check" data-disabled="true">
  <input type="checkbox" class="jl-check__input" disabled />
  <span class="jl-check__box">…</span>
  <span class="jl-check__body"><span class="jl-check__label">Disabled</span></span>
</label>
vue
<template>
  <Checkbox indeterminate label="Select all" />
  <Checkbox invalid label="I accept the terms" description="Required to continue." />
  <Checkbox disabled label="Disabled" />
</template>
tsx
<Checkbox indeterminate label="Select all" />
<Checkbox invalid label="I accept the terms" description="Required to continue." />
<Checkbox disabled label="Disabled" />

Props

React

Checkbox extends React.InputHTMLAttributes<HTMLInputElement> (minus type), so checked, defaultChecked, onChange, name, etc. pass through to the input.

PropTypeDefaultDescription
labelReact.ReactNodeLabel beside the box
descriptionReact.ReactNodeSecondary line under the label
indeterminatebooleanfalseRender the mixed dash
invalidbooleanfalseError styling on the box

Vue

Checkbox supports v-model (boolean); other attributes (name, …) fall through to the input.

PropTypeDefaultDescription
labelstringLabel beside the box
descriptionstringSecondary line under the label
indeterminatebooleanfalseRender the mixed dash
invalidbooleanfalseError styling on the box
disabledbooleanfalseDim and lock
modelValuebooleanfalseChecked state (v-model)

Slots: default — label content (alternative to the label prop).

CSS classes (HTML)

ClassPurpose
.jl-checkThe <label> wrapper — always required
.jl-check__inputThe visually-hidden <input type="checkbox">
.jl-check__boxThe drawn box (holds the check mark + dash)
.jl-check__mark / .jl-check__dashChecked tick / indeterminate dash
.jl-check__body / __label / __descText column, label, and description
[data-invalid="true"]Error styling (on the label)
[data-disabled="true"]Disabled styling (on the label)