Skip to content

shadcn.io is an independent project built on shadcn/ui

Components

Free

Checkbox for Radix UI

A yes or no for terms, filters, and row picks that applies when the form is submitted. In React with Radix UI, clicking the label toggles the box too.

The box and its label sit on one line. The box alone is a small target, so the label has to toggle it too.

Use it when the choice waits for the form to be submitted. A Switch fits a setting that applies the moment it changes. In React, Radix UI tracks a mixed state when only some children are on.

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Checkbox anatomy: root, control, indicator, label
Checkbox
โ”œโ”€โ”€ CheckboxLabel
โ”œโ”€โ”€ checkboxVariants
โ””โ”€โ”€ CheckboxIndicator

Usage

import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
<FieldGroup className="w-fit whitespace-nowrap">
  <Field orientation="horizontal">
    <Checkbox name="terms" />
    <FieldLabel>Accept terms</FieldLabel>
  </Field>
</FieldGroup>

Accessibility

Space
Toggle the checkbox.

Demos

Invalid

aria-invalid on the checkbox and data-invalid on the field turn on the error styling for a terms box that was left empty. The words of the error still have to live somewhere the person can read. Use the invalid state after submit, when acceptance was required and did not happen. A disabled box is not an error: it is a choice the person cannot make.

Preview width

Basic

One checkbox, one label, a name for the form. That is the smallest useful version: the label is the hit target, and the name is how the value shows up on submit. Start here for a single agreement. Add a description only when the label's words are not enough to explain the consequence, and a group only when there are several related boxes.

Preview width

Description

The terms box is already checked, and a second line under the label says you agree to the terms. FieldContent stacks the label and that description so the checkbox stays aligned to the first line, not the whole block. Use the extra line when the consequence is easy to miss, such as a billing change or a data share. Keep that line to the consequence, shorter than a paragraph.

Preview width

Disabled

Notifications cannot be toggled. disabled is on the checkbox and data-disabled is on the field, so the label fades with the box and clicks do nothing. Use this for a preference the current plan or role does not allow, and say why nearby if it is not obvious. Hiding the row is the alternative when the choice should not even be visible.

Preview width

Group

Hard disks and external disks start checked, servers does not, and the set is labeled Desktop. Each box has its own name, because these are independent choices, not a single value. Use a fieldset when several checkboxes answer one question. A Listbox is a better fit once the list is long enough that a stack of boxes becomes a chore.

Preview width

Table

Each person row has a checkbox, the header checkbox selects or clears every row, and Sarah starts selected. Keep the selected ids in state, and mark the row when it is in that set, so the highlight and the box agree. Use this for bulk actions on a Table. For a handful of options that are not records, the grouped checkboxes are simpler.

Preview width

Rtl

The group sets dir to rtl. The checkbox stays on the start side of the row, and the label ู‚ุจูˆู„ ุงู„ุดุฑูˆุท follows it, so the line reads correctly without swapping the markup. Direction belongs on the group when this block can sit inside a left-to-right page. Checking the box works the same either way.

Preview width

FAQ

Should I use a Checkbox or a Switch?

Use a Checkbox for a choice that takes effect when the form is submitted, like accepting terms or picking filters. Use a Switch for a setting that applies the moment it changes, and a Radio Group when only one option can be picked.

How do I control a Checkbox's checked state in React?

Hold the checked state yourself and pass it back on every change. Pass checked and update it in onCheckedChange, which receives true, false or "indeterminate". Use defaultChecked when you only need a starting value.

How do I show an indeterminate Checkbox?

Use the indeterminate state on a parent whose children are only partly checked, and compute it from the children yourself. Set checked to "indeterminate".

How do I build a select-all Checkbox for a table?

Keep the selected row ids in a set. The header checkbox is checked when every row is selected, indeterminate when only some are, and toggles all of them when clicked. The Table demo shows the whole pattern.

How do I add a label to a Checkbox in Radix UI?

Put the Checkbox and a FieldLabel in a horizontal Field, so clicking the text toggles the box and gives a larger tap target on phones. Give the checkbox an id and point the label's htmlFor at it.

How do I show a Checkbox error in a form?

Set invalid on the surrounding Field: the field gets data-invalid and the checkbox is marked invalid, so the box and the label both turn red. Add a FieldError with the message. The Invalid demo shows it.

Does the Checkbox submit with a native form?

Yes. Give it a name and it submits through a hidden input when checked, with value as the submitted value. With React Hook Form, TanStack Form or Formisch, connect the field's value to the checked state and its change handler.

How do I change the Checkbox size or colors?

Edit the checkbox file in your project's components/ui folder: the box, the check icon and their sizes are classes there. Its states come through as data attributes, listed in the API reference below, so you can style checked, disabled and invalid boxes with Tailwind variants.

API Reference

Checkbox

<label> data-slot="checkbox"

PropType
checked?boolean | "indeterminate"

Whether it's checked. Pair with onCheckedChange to control it.

Type
boolean | "indeterminate"
defaultChecked?boolean | "indeterminate"

Whether it starts checked, when you don't control checked.

Type
boolean | "indeterminate"
onCheckedChange?{ bivarianceHack(checked: CheckedState): void; }["bivarianceHack"]

Called when the checked state changes.

Type
{ bivarianceHack(checked: CheckedState): void; }["bivarianceHack"]
required?boolean

Whether a value is required to submit its form.

asChild?boolean

Merge props onto the child element instead of rendering a host.

className?string

Merged with the part's classes.

CheckboxIndicator

<div> data-slot="checkbox-indicator"

PropType
forceMount?true

Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.