CheckboxDesign system
ComponentProduct

Checkbox

Checkbox with checked, unchecked, and disabled states.

npx context-ds add checkbox
In the product

Usage

Use it for

Multiple choices and table row selection.

Avoid

  • Checkboxes for settings that apply at once (use a switch)

Dependencies: @radix-ui/react-checkbox, lucide-react

Example

examples/checkbox.tsx
"use client";import { useState } from "react";import { Checkbox } from "@/components/ui/checkbox";import { Label } from "@/components/ui/label";// Checked, unchecked, mixed (some of a group picked) and disabled.export function Product() {  const [selected, setSelected] = useState(["scrape"]);  const toggle = (name: string, checked: boolean) => setSelected((all) => checked ? [...all, name] : all.filter((value) => value !== name));  return (    <div className="grid gap-3">      <div className="flex items-center gap-2.5">        <Checkbox id="cb-all" checked={selected.length === 2 ? true : selected.length ? "indeterminate" : false} onCheckedChange={(checked) => setSelected(checked ? ["scrape", "search"] : [])} />        <Label htmlFor="cb-all">All APIs</Label>      </div>      <div className="grid gap-3 pl-6.5">        <div className="flex items-center gap-2.5">          <Checkbox id="cb-scrape" checked={selected.includes("scrape")} onCheckedChange={(checked) => toggle("scrape", checked === true)} />          <Label htmlFor="cb-scrape">Scrape</Label>        </div>        <div className="flex items-center gap-2.5">          <Checkbox id="cb-search" checked={selected.includes("search")} onCheckedChange={(checked) => toggle("search", checked === true)} />          <Label htmlFor="cb-search">Search</Label>        </div>        <div className="flex items-center gap-2.5">          <Checkbox id="cb-crawl" disabled />          <Label htmlFor="cb-crawl">Crawl (on Pro)</Label>        </div>      </div>    </div>  );}

Source

components/ui/checkbox.tsx
"use client";import * as React from "react";import * as CheckboxPrimitive from "@radix-ui/react-checkbox";import { Check, Minus } from "lucide-react";import { cn } from "@/lib/utils";// A 16px box with a hairline edge; checked fills brand blue with a white check.function Checkbox({ className, ...props }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {  return (    <CheckboxPrimitive.Root      data-slot="checkbox"      className={cn(        "peer grid size-4 shrink-0 place-items-center rounded-sm border border-line-strong bg-surface text-white outline-none transition-[background-color,border-color] duration-150 ease-out focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-brand data-[state=checked]:bg-brand data-[state=indeterminate]:border-brand data-[state=indeterminate]:bg-brand",        className,      )}      {...props}    >      <CheckboxPrimitive.Indicator data-slot="checkbox-indicator" className="grid place-items-center [&_svg]:size-3">        {props.checked === "indeterminate" ? <Minus strokeWidth={2.5} /> : <Check strokeWidth={2.5} />}      </CheckboxPrimitive.Indicator>    </CheckboxPrimitive.Root>  );}export { Checkbox };

Reference: none in PR 1045 (the dashboard has no checkbox; the site's DotCheckbox in src/components/ui/dot-checkbox.tsx is a static mark).