Checkbox
A square box for one yes-or-no choice. Checked fills it with ink, so the state reads without colour.
Loading the live example…
"use client"
import { useState } from "react"
import { CheckboxField } from "@/components/keyline/ui/checkbox"
const TASKS = [
{ id: "copier", label: "Turn off the copier", description: "It overheats if it runs all night." },
{ id: "dock", label: "Lock the warehouse door", description: "Darryl leaves by the loading dock at 5." },
{ id: "fridge", label: "Clear the kitchen fridge", description: "Anything unlabelled goes. Ask Angela first." },
{ id: "alarm", label: "Set the alarm", description: "The code is on the card in Dwight's desk." },
]
export function ClosingChecklist() {
const [done, setDone] = useState<string[]>(["copier"])
const toggle = (id: string, on: boolean) => setDone(on ? [...done, id] : done.filter((d) => d !== id))
return (
<div className="grid max-w-[480px] gap-3">
<div className="grid gap-1">
{TASKS.map((t) => (
<CheckboxField key={t.id} label={t.label} description={t.description} checked={done.includes(t.id)} onCheckedChange={(on) => toggle(t.id, on)} />
))}
</div>
<p role="status" className="m-0 text-[14px] text-kl-ink-2">
{done.length === TASKS.length ? "Office closed for the night. See you at 9." : `${done.length} of ${TASKS.length} done before you leave.`}
</p>
</div>
)
}Installation
npx shadcn@latest add @keyline-ui/checkboxRun it where your components.json is. The first time, map the @keyline-ui registry: one command, in Installation.
Usage
import { CheckboxField } from "@/components/keyline/ui/checkbox"<CheckboxField
label="Lock the warehouse door"
description="Darryl leaves by the loading dock at 5."
checked={locked}
onCheckedChange={setLocked}
/>Examples
Bare box
Checkbox on its own, for a list or a table row where the row already says what it is. Give it an aria-label.
Loading the live example…
"use client"
import { useState } from "react"
import { Button } from "@/components/keyline/ui/button"
import { Checkbox } from "@/components/keyline/ui/checkbox"
const INVOICES = [
{ id: "INV-2201", client: "Blue Cross of Pennsylvania", amount: "$3,420.00" },
{ id: "INV-2204", client: "Lackawanna County", amount: "$812.50" },
{ id: "INV-2207", client: "Scranton Business Park", amount: "$1,284.00" },
]
export function PrintInvoices() {
const [picked, setPicked] = useState<string[]>([])
const [printed, setPrinted] = useState<string | null>(null)
return (
<div className="grid max-w-[520px] gap-3">
<ul className="m-0 grid list-none gap-2 p-0 text-[14px]" aria-label="Unpaid invoices">
{INVOICES.map((inv) => (
<li key={inv.id} className="grid grid-cols-[auto_auto_minmax(0,1fr)_auto] items-center gap-x-3">
<Checkbox
aria-label={`Print ${inv.id}`}
checked={picked.includes(inv.id)}
onCheckedChange={(on) => setPicked(on ? [...picked, inv.id] : picked.filter((p) => p !== inv.id))}
/>
<span className="font-kl-mono whitespace-nowrap">{inv.id}</span>
<span className="truncate">{inv.client}</span>
<span className="tabular-nums text-kl-ink-2">{inv.amount}</span>
</li>
))}
</ul>
<div className="flex flex-wrap items-center gap-3">
<Button
disabled={!picked.length}
onClick={() => {
setPrinted(`Sent ${picked.length} to the printer by the kitchen.`)
setPicked([])
}}
>
{picked.length ? `Print ${picked.length} ${picked.length === 1 ? "invoice" : "invoices"}` : "Print invoices"}
</Button>
<p role="status" className="m-0 text-[14px] text-kl-ink-2">
{printed}
</p>
</div>
</div>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | Default — | On CheckboxField: the row's name. The whole row toggles the box. |
description | ReactNode | Default — | A line under the label, read out with it. |
checked | boolean | Default — | With onCheckedChange. Or start with defaultChecked. |
indeterminate | boolean | Default false | Draws a bar: some of a set is checked. Checkbox group sets it for you on its All row. |
layout | "control" | "cell" | Default "control" | On CheckboxField: cell is a row inside another frame, such as a panel. |
name | string | Default — | Submits the box with a form. |
For several choices that answer one question, use Checkbox group. Built on Base UI Checkbox; its other props pass through.