# Checkbox

A control that allows users to toggle between checked, unchecked, and indeterminate states.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. An agent skill is available at [/.well-known/agent-skills/site-skill.md](/.well-known/agent-skills/site-skill.md).





<ComponentThemeTabs>
  <ThemeTab name="mint">
    <PreviewWithCode name="checkbox">
      <div className="flex items-center gap-2">
        <Checkbox id="demo-ny" />

        <label htmlFor="demo-ny" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
          Accept terms and conditions
        </label>
      </div>
    </PreviewWithCode>
  </ThemeTab>

  <ThemeTab name="berries">
    <PreviewWithCode name="checkbox">
      <div className="flex items-center gap-2">
        <Checkbox id="demo-f8" />

        <label htmlFor="demo-f8" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
          Accept terms and conditions
        </label>
      </div>
    </PreviewWithCode>
  </ThemeTab>

  <ThemeTab name="citrine">
    <PreviewWithCode name="checkbox">
      <div className="flex items-center gap-2">
        <Checkbox id="demo-ski" />

        <label htmlFor="demo-ski" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
          Accept terms and conditions
        </label>
      </div>
    </PreviewWithCode>
  </ThemeTab>

  <ThemeTab name="cinnamon">
    <PreviewWithCode name="checkbox">
      <div className="flex items-center gap-2">
        <Checkbox id="demo-ice" />

        <label htmlFor="demo-ice" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
          Accept terms and conditions
        </label>
      </div>
    </PreviewWithCode>
  </ThemeTab>
</ComponentThemeTabs>

## States [#states]

### Checked [#checked]

<div className="my-6 flex items-center gap-2">
  <Checkbox id="checked" />

  <label htmlFor="checked" className="text-sm font-medium leading-none">
    Checked
  </label>
</div>

### Unchecked [#unchecked]

<div className="my-6 flex items-center gap-2">
  <Checkbox id="unchecked" />

  <label htmlFor="unchecked" className="text-sm font-medium leading-none">
    Unchecked
  </label>
</div>

### Disabled [#disabled]

<div className="my-6 flex flex-col gap-3">
  <div className="flex items-center gap-2">
    <Checkbox id="disabled-unchecked" />

    <label htmlFor="disabled-unchecked" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
      Disabled
    </label>
  </div>

  <div className="flex items-center gap-2">
    <Checkbox id="disabled-checked" />

    <label htmlFor="disabled-checked" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
      Disabled checked
    </label>
  </div>
</div>

## With Description [#with-description]

Pair the checkbox with a description label for more context.

<div className="my-6 flex gap-2">
  <Checkbox id="email" className="mt-0.5" />

  <div className="grid gap-1">
    <label htmlFor="email" className="text-sm font-medium leading-none">
      Marketing emails
    </label>

    <span className="block text-sm text-muted-foreground">
      Receive emails about new products and features.
    </span>
  </div>
</div>

## Group [#group]

Use multiple checkboxes for multi-select lists.

<div className="my-6 flex flex-col gap-3">
  <div className="flex items-center gap-2">
    <Checkbox id="recents" />

    <label htmlFor="recents" className="text-sm font-medium leading-none">
      Recents
    </label>
  </div>

  <div className="flex items-center gap-2">
    <Checkbox id="home" />

    <label htmlFor="home" className="text-sm font-medium leading-none">
      Home
    </label>
  </div>

  <div className="flex items-center gap-2">
    <Checkbox id="apps" />

    <label htmlFor="apps" className="text-sm font-medium leading-none">
      Applications
    </label>
  </div>

  <div className="flex items-center gap-2">
    <Checkbox id="desktop" />

    <label htmlFor="desktop" className="text-sm font-medium leading-none">
      Desktop
    </label>
  </div>
</div>

## Props [#props]

### Checkbox [#checkbox]

| Prop              | Type                                            | Default | Description                          |
| ----------------- | ----------------------------------------------- | ------- | ------------------------------------ |
| `checked`         | `boolean \| "indeterminate"`                    | —       | Controlled checked state             |
| `defaultChecked`  | `boolean`                                       | —       | Initial checked state (uncontrolled) |
| `onCheckedChange` | `(checked: boolean \| "indeterminate") => void` | —       | Callback when state changes          |
| `disabled`        | `boolean`                                       | `false` | Prevents interaction                 |
| `required`        | `boolean`                                       | `false` | Marks the field as required          |
| `name`            | `string`                                        | —       | Form field name                      |
| `value`           | `string`                                        | `"on"`  | Form field value when checked        |
| `className`       | `string`                                        | —       | Additional CSS classes               |

## Usage [#usage]

```tsx
import { Checkbox } from "@/components/ui/checkbox";

// With label
<div className="flex items-center gap-2">
  <Checkbox id="terms" />
  <label
    htmlFor="terms"
    className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
  >
    Accept terms and conditions
  </label>
</div>

// Controlled
const [checked, setChecked] = useState(false);
<Checkbox
  checked={checked}
  onCheckedChange={setChecked}
/>

// Indeterminate (e.g. select-all pattern)
<Checkbox checked="indeterminate" />

// In a form
<Checkbox id="marketing" name="marketing" value="yes" />
```

## Specs [#specs]

```md
# Mint — Checkbox Specs

## Component
- name: checkbox
- file: registry/mint/checkbox.tsx
- installs to: components/ui/checkbox.tsx
- dependencies: radix-ui, lucide-react

## What is it
A binary toggle input for forms and settings. Supports three states:
unchecked, checked, and indeterminate (for select-all patterns). Uses
Radix UI's Checkbox primitive for accessible keyboard and screen reader
support. Renders a Check icon (stroke-[3]) when checked.

## Visual identity
Small (size-4 / 16px), square with rounded-[4px] corners — not fully
rounded. Thin border (border-input) in rest state, filled primary on
checked. Clean and dense — designed to sit in lists and forms without
visual weight.

## Design tokens
--input: oklch(0.88 0.04 155 / 60%)      — unchecked border
--primary: oklch(0.5 0.14 155)           — checked background + border
--primary-foreground: oklch(1 0 0)       — check icon color
--ring: oklch(0.5 0.14 155)              — focus ring
--destructive: oklch(0.55 0.25 15)       — aria-invalid border

## Dark theme
--input: oklch(0.32 0.05 155 / 40%)
--primary: oklch(0.62 0.15 155)
--primary-foreground: oklch(0.1 0 0)

## States
- unchecked:      border-input, transparent background
- checked:        bg-primary text-primary-foreground border-primary
- indeterminate:  bg-primary text-primary-foreground border-primary
- focus-visible:  border-ring + ring-ring/50 + ring-[3px]
- disabled:       opacity-50 cursor-not-allowed (via peer, label follows)
- aria-invalid:   border-destructive + ring-destructive/20

## Label pattern
Always use a <label> with matching htmlFor. Apply peer-disabled classes
on the label to visually sync disabled state:
  className="peer-disabled:cursor-not-allowed peer-disabled:opacity-70"

## Conventions
- Always pair with a <label htmlFor="..."> for accessibility
- Use mt-0.5 on Checkbox when pairing with multi-line description text
- For select-all: set checked="indeterminate" and handle onCheckedChange
- In React Hook Form: use <Controller> with onCheckedChange={field.onChange}
- Do not use Checkbox for mutually exclusive choices — use RadioGroup instead
```

## Installation [#installation]

<CommandBox componentName="checkbox" className="mt-2" />
