Checkbox

A binary choice with a precise, legible state.

fieldform
Preview
Checkbox preview
One email a week, never more.

When to use

  • Independent on and off choices confirmed by a submit, such as accepting terms.
  • Parent rows that show a partial selection through the indeterminate state.

When not to use

  • Use switch for settings that apply immediately.
  • Use radio-group when only one option can be chosen.
  • Use chip-group for filter facets people toggle often.

shadcn CLI

Also installs (1)

  • manicat-foundation
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "checkbox",
  "type": "registry:ui",
  "title": "Checkbox",
  "description": "A binary choice with a precise, legible state.",
  "categories": [
    "inputs"
  ],
  "dependencies": [
    "@radix-ui/react-checkbox",
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json"
  ],
  "files": [
    {
      "path": "registry/components/checkbox/checkbox.tsx",
      "type": "registry:component",
      "target": "@components/manicat/checkbox/checkbox.tsx"
    },
    {
      "path": "registry/components/checkbox/checkbox.module.css",
      "type": "registry:component",
      "target": "@components/manicat/checkbox/checkbox.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/checkbox",
  "meta": {
    "tier": "free",
    "kind": "component",
    "docs": "https://manicat.viraza.net/components/checkbox",
    "markdown": "https://uiarc.dev/components/checkbox/markdown",
    "tags": [
      "field",
      "form"
    ]
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

import { useState } from "react";
import { Checkbox } from "@/components/manicat/checkbox/checkbox";

export function CheckboxExample() {
  const [checked, setChecked] = useState<boolean | "indeterminate">("indeterminate");

  return (
    <div className="grid gap-3">
      <Checkbox
        label="Email me about releases"
        checked={checked === "indeterminate" ? "indeterminate" : checked}
        onCheckedChange={(next) => setChecked(next === true ? true : next === "indeterminate" ? "indeterminate" : false)}
      />
      <Checkbox label="Include a digest" description="One email a week, never more." />
      <Checkbox label="Locked" disabled />
    </div>
  );
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

Select all A parent checkbox that shows the indeterminate state while only some children are checked.

Select all A parent checkbox that shows the indeterminate state while only some children are checked. preview

Keyboard interactions

KeysAction
SpaceToggles the checkbox.

Accessibility

  • Radix renders a button with role="checkbox" and aria-checked, including "mixed" for indeterminate.
  • The label is a real label element tied by id; description is linked through aria-describedby.
  • The drawn mark is aria-hidden.

Motion

  • The fill scales in on a snappy spring while the check path draws; switching to indeterminate morphs the same path into a dash.
  • Reduced motion applies every state change instantly.

Responsive behavior

  • The hit box is a full control-height square, so it stays easy to tap even though the drawn box is smaller.
  • The label and description wrap beside the box; the box stays top-aligned with the first line.

Performance

  • A single spring on the fill and a path draw per toggle; long lists of checkboxes are fine.

Notes for AI

  • Use for independent on/off choices in forms. Use switch for settings that apply immediately and chip-group for filter facets.
  • Set checked="indeterminate" on a parent checkbox when only some children are selected.
  • Radix renders a hidden native input when name is set, so it submits with forms.