1
ComponentsForm Controls

Checkbox

Checkbox represents a Boolean choice or one option within a multi-select group.

Purpose

Checkbox represents one Boolean decision or one option in a multi-select group.

Labeled checkbox

You can change this setting later in your profile.

import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";

export function Example() {
  return (
    <Field>
      <FieldLabel>
        <Checkbox defaultChecked />
        Receive product updates
      </FieldLabel>
      <FieldDescription>
        You can change this setting later in your profile.
      </FieldDescription>
    </Field>
  );
}

Installation

With the Siteplane registry alias configured, add the component and import the installed source from your app.

CLI

pnpm dlx shadcn@4.16.1 add @siteplane/checkbox

Import

import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";

Need the machine-readable source metadata? View registry JSON.

Usage

Use Checkbox for a labeled boolean choice. Checked and unchecked are states of the same primitive.

import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";

export function Example() {
  return (
    <Field>
      <FieldLabel>
        <Checkbox defaultChecked />
        Receive product updates
      </FieldLabel>
      <FieldDescription>
        You can change this setting later in your profile.
      </FieldDescription>
    </Field>
  );
}

Examples

States, sizes, groups and form integration stay together so the choice model remains clear. Form examples use Field and Form for labels, errors and submitted state.

States

import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldError, FieldLabel } from "@/components/ui/field";
import { Label } from "@/components/ui/label";

export function States() {
  return (
    <div className="grid gap-4">
      <Label><Checkbox defaultChecked />Checked</Label>
      <Label><Checkbox indeterminate />Indeterminate</Label>
      <Label><Checkbox disabled />Disabled</Label>
      <Field>
        <FieldLabel><Checkbox aria-invalid />Invalid</FieldLabel>
        <FieldError>Selection is required.</FieldError>
      </Field>
    </div>
  );
}

Sizes

import { Checkbox } from "@/components/ui/checkbox";

export function Sizes() {
  return (
    <div className="flex items-center gap-4">
      <Checkbox aria-label="Small checkbox" size="sm" />
      <Checkbox aria-label="Default checkbox" />
      <Checkbox aria-label="Large checkbox" size="lg" />
      <Checkbox aria-label="Extra large checkbox" size="xl" />
    </div>
  );
}

Checkbox group

import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

export function Channels() {
  return (
    <CheckboxGroup aria-label="Notification channels" defaultValue={["email", "in-app"]}>
      <Label><Checkbox value="email" />Email updates</Label>
      <Label><Checkbox value="in-app" />In-app activity</Label>
      <Label><Checkbox value="sms" />SMS alerts</Label>
    </CheckboxGroup>
  );
}

Card choice

import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";

export function CardChoice() {
  return (
    <Label className="items-start rounded-lg border p-3">
      <Checkbox defaultChecked />
      <span>Enable notifications</span>
    </Label>
  );
}

Form integration

This demo submits the checkbox value without leaving the page.

Not submitted
import { useState, type FormEvent } from "react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";
import { Form } from "@/components/ui/form";

export function CheckboxForm() {
  const [status, setStatus] = useState("Not submitted");

  function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    setStatus(formData.get("terms") === "yes" ? "Terms accepted" : "Terms missing");
  }

  return (
    <Form onSubmit={onSubmit}>
      <Field name="terms">
        <FieldLabel>
          <Checkbox value="yes" />
          Accept terms and conditions
        </FieldLabel>
        <FieldDescription>
          This demo submits the checkbox value without leaving the page.
        </FieldDescription>
      </Field>
      <Button type="submit">Submit</Button>
      <span>{status}</span>
    </Form>
  );
}

API Reference

The reference lists the source-owned exports and props that are easy to miss in visual examples. Inherited Base UI props remain available unless the wrapper narrows them.

  • Use controlled checked and onCheckedChange or uncontrolled defaultChecked.
  • indeterminate represents a mixed parent state; it is not a selected value.
  • size accepts "sm", "default", "lg", and "xl" and otherwise inherits SiteplaneUIProvider controlSize.
  • Use Checkbox Group for related multi-select options.

Motion

Component motion uses the shared Siteplane motion contract. See the global motion guide for provider setup, tokens and reduced-motion behavior.

  • Checked and indeterminate indicators use native checkbox motion and central exit tokens.
  • Reduced motion moves the indicator directly to its final state.
  • Pointer, hover, focus, invalid, and disabled states remain native.

Accessibility

  • Every Checkbox needs visible label text or an accessible label.
  • Connect invalid state to the Checkbox and render a visible FieldError.
  • Make row or card compositions clickable without replacing Checkbox semantics.
  • Use indeterminate state only to summarize partial child selection.

Implementation Guidance

  • Do not use raw checkbox inputs for visible Siteplane controls.
  • Use Checkbox Group for related options.
  • Preserve native indicator, focus, cursor, invalid, disabled, and motion behavior.

On This Page