Skip to content
  1. Keyline UI
  2. Checkbox
Keyline UIComponents
  • Get started
    • Installation
    • Theming
    • Modes
    • Configuration
    • Composition
  • Actions
    • Button
    • Button group
    • Split button
    • Toggle
    • Toggle group
    • Toolbar
    • Menu
    • Menubar
    • Context menu
  • Inputs
    • Field and form
    • Checkbox
    • Checkbox group
    • Radio group
    • Switch
    • Slider
    • Segmented
    • Select
    • Native select
    • Combobox
    • Multiselect
    • Number field
    • OTP field
    • Time field
    • Date picker and calendar
    • Date range
  • Data
    • Table
    • Chart
    • Stat and meter
    • Status and badge
    • Progress
    • Skeleton
    • Empty
    • Avatar
    • Kbd
    • Marker
  • Navigation
    • Tabs
    • Breadcrumb
    • Pagination
    • Nav
    • Navigation menu
    • Command menu
  • Overlays
    • Dialog
    • Alert dialog
    • Drawer
    • Sheet
    • Popover
    • Hover card
    • Tooltip
    • Toast
    • Notice
  • Layout
    • App shell
    • Sidebar
    • Panel
    • Resizable
    • Scroll area
    • Accordion
    • Collapsible
    • Carousel
    • Inspector
    • Item
    • Direction
  • Conversation
    • Message
    • Bubble
    • Message scroller
    • Attachment
    • Questionnaire
  • Blocks
    • Shipments

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/checkbox

Run 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

PropTypeDefaultDescription
labelReactNodeDefault —On CheckboxField: the row's name. The whole row toggles the box.
descriptionReactNodeDefault —A line under the label, read out with it.
checkedbooleanDefault —With onCheckedChange. Or start with defaultChecked.
indeterminatebooleanDefault falseDraws 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.
namestringDefault —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.

Sheet 17 of 73PreviousField and formNextCheckbox group
On this page