Handle independent choices in forms and settings. Keep the control simple, add supporting text, or place it in a selectable card.
import * as React from "react"import { Card, CardContent } from "@/components/ui/card"import { Checkbox } from "@/components/ui/checkbox"import { cn } from "@/lib/utils"export function Example() { const [checked, setChecked] = React.useState(false) return ( <> <label className="flex items-center gap-2.5 text-sm tracking-wide"> <Checkbox defaultChecked id="basic" /> Sync local registry on save </label> <label className="flex items-start gap-2.5"> <Checkbox id="described" className="mt-0.5" /> <span className="grid gap-1"> <span className="text-sm font-medium tracking-wide"> Watch theme tokens </span> <span className="text-sm text-muted-foreground"> Rebuild docs when CSS variables change under globals.css. </span> </span> </label> <label className="flex items-center gap-2.5 text-sm tracking-wide opacity-60"> <Checkbox disabled id="disabled" /> Publish package — unlock after review </label> <label className="block w-full cursor-pointer"> <Card className={cn("py-0", !checked && "bg-transparent")}> <CardContent className="flex items-start gap-2.5 py-3"> <Checkbox id="card" checked={checked} onCheckedChange={setChecked} className="mt-0.5" /> <span className="grid gap-1"> <span className="text-sm font-medium tracking-wide"> Include in docs build </span> <span className="text-sm text-muted-foreground"> Ships markdown, demos, and tokens with the registry export. </span> </span> </CardContent> </Card> </label> </> )}Installation
npx @arctis-sh/@arctis-sh/ui@latest add checkboxUsage
import { Checkbox } from "@/components/ui/checkbox"<label className="flex items-center gap-2.5 text-sm tracking-wide"> <Checkbox id="sync" /> Sync local registry on save</label><Checkbox checked={checked} onCheckedChange={setChecked}/>Basic
The common patterns: a plain row, supporting description, disabled state, and selectable card.
import * as React from "react"import { Card, CardContent } from "@/components/ui/card"import { Checkbox } from "@/components/ui/checkbox"import { cn } from "@/lib/utils"export function Example() { const [checked, setChecked] = React.useState(false) return ( <> <label className="flex items-center gap-2.5 text-sm tracking-wide"> <Checkbox defaultChecked id="basic" /> Sync local registry on save </label> <label className="flex items-start gap-2.5"> <Checkbox id="described" className="mt-0.5" /> <span className="grid gap-1"> <span className="text-sm font-medium tracking-wide"> Watch theme tokens </span> <span className="text-sm text-muted-foreground"> Rebuild docs when CSS variables change under globals.css. </span> </span> </label> <label className="flex items-center gap-2.5 text-sm tracking-wide opacity-60"> <Checkbox disabled id="disabled" /> Publish package — unlock after review </label> <label className="block w-full cursor-pointer"> <Card className={cn("py-0", !checked && "bg-transparent")}> <CardContent className="flex items-start gap-2.5 py-3"> <Checkbox id="card" checked={checked} onCheckedChange={setChecked} className="mt-0.5" /> <span className="grid gap-1"> <span className="text-sm font-medium tracking-wide"> Include in docs build </span> <span className="text-sm text-muted-foreground"> Ships markdown, demos, and tokens with the registry export. </span> </span> </CardContent> </Card> </label> </> )}Card
Place the control in a Card with a title and description. The outlined card fills when selected.
import * as React from "react"import { Card, CardContent } from "@/components/ui/card"import { Checkbox } from "@/components/ui/checkbox"import { cn } from "@/lib/utils"export function Example() { const [checked, setChecked] = React.useState(false) return ( <label className="block w-full cursor-pointer"> <Card className={cn("py-0", !checked && "bg-transparent")}> <CardContent className="flex items-start gap-2.5 py-3"> <Checkbox id="card-option" checked={checked} onCheckedChange={setChecked} className="mt-0.5" /> <span className="grid gap-1"> <span className="text-sm font-medium tracking-wide"> Include in docs build </span> <span className="text-sm text-muted-foreground"> Ships markdown, demos, and tokens with the registry export. </span> </span> </CardContent> </Card> </label> )}Controlled
Pass checked and onCheckedChange when the parent owns the value. Use defaultChecked to set an initial uncontrolled value.
import * as React from "react"import { Checkbox } from "@/components/ui/checkbox"export function Example() { const [checked, setChecked] = React.useState(false) return ( <label className="flex items-center gap-2.5 text-sm tracking-wide"> <Checkbox id="dark-preview" checked={checked} onCheckedChange={setChecked} /> Preview docs in dark mode {checked ? "(on)" : "(off)"} </label> )}Description
Add a short title and muted description when the choice needs more context.
import { Checkbox } from "@/components/ui/checkbox"export function Example() { return ( <label className="flex items-start gap-2.5"> <Checkbox id="watch-tokens" className="mt-0.5" /> <span className="grid gap-1"> <span className="text-sm font-medium tracking-wide"> Watch theme tokens </span> <span className="text-sm text-muted-foreground"> Rebuild docs when CSS variables change under globals.css. </span> </span> </label> )}Disabled
Set disabled to lock the control. Dim the label as well so the entire row reads as inactive.
import { Checkbox } from "@/components/ui/checkbox"export function Example() { return ( <label className="flex items-center gap-2.5 text-sm tracking-wide opacity-60"> <Checkbox disabled id="publish-locked" /> Publish package — unlock after review </label> )}Invalid
Set aria-invalid when validation fails, and use a destructive color for the related label or message.
import { Checkbox } from "@/components/ui/checkbox"export function Example() { return ( <label className="flex items-center gap-2.5 text-sm font-medium tracking-wide text-destructive"> <Checkbox id="license" aria-invalid /> Accept the license </label> )}Group
Arrange labeled checkboxes in a list for settings with several independent choices.
Include in the docs build
Pick what ships when you run the registry export.
import * as React from "react"import { Checkbox } from "@/components/ui/checkbox"const items = [ { id: "docs", label: "Markdown pages" }, { id: "demos", label: "Live demos" }, { id: "tokens", label: "Theme tokens" }, { id: "changelog", label: "Changelog entries" },] as constexport function Example() { const [selected, setSelected] = React.useState<string[]>(["docs", "demos"]) function toggle(id: string, next: boolean) { setSelected((prev) => next ? [...prev, id] : prev.filter((entry) => entry !== id), ) } return ( <div className="grid gap-3"> <div className="grid gap-1"> <p className="text-sm font-medium tracking-wide"> Include in the docs build </p> <p className="text-sm text-muted-foreground"> Pick what ships when you run the registry export. </p> </div> <div className="grid gap-2.5"> {items.map((item) => ( <label key={item.id} className="flex items-center gap-2.5 text-sm tracking-wide" > <Checkbox id={item.id} checked={selected.includes(item.id)} onCheckedChange={(next) => toggle(item.id, next)} /> {item.label} </label> ))} </div> </div> )}Indeterminate
Set checked="indeterminate" on a parent when only some child options are selected. Selecting the parent checks them all.
import * as React from "react"import { Checkbox } from "@/components/ui/checkbox"const parts = [ { id: "button", label: "Button" }, { id: "badge", label: "Badge" }, { id: "alert", label: "Alert" },] as constexport function Example() { const [selected, setSelected] = React.useState<string[]>(["button"]) const allChecked = selected.length === parts.length const someChecked = selected.length > 0 && !allChecked function toggleAll(next: boolean) { setSelected(next ? parts.map((part) => part.id) : []) } function toggle(id: string, next: boolean) { setSelected((prev) => next ? [...prev, id] : prev.filter((entry) => entry !== id), ) } return ( <div className="grid gap-3"> <label className="flex items-center gap-2.5 text-sm font-medium tracking-wide"> <Checkbox id="all-parts" checked={allChecked ? true : someChecked ? "indeterminate" : false} onCheckedChange={toggleAll} /> Export UI parts </label> <div className="ms-6 grid gap-2.5"> {parts.map((part) => ( <label key={part.id} className="flex items-center gap-2.5 text-sm tracking-wide" > <Checkbox id={part.id} checked={selected.includes(part.id)} onCheckedChange={(next) => toggle(part.id, next)} /> {part.label} </label> ))} </div> </div> )}API Reference
Checkbox
| Prop | Type | Default |
|---|---|---|
| checked | boolean | "indeterminate" | — |
| defaultChecked | boolean | false |
| onCheckedChange | (checked: boolean) => void | — |
| disabled | boolean | false |
| className | string | — |
<Checkbox checked={checked} onCheckedChange={setChecked} />