Checkbox

A checkbox component built on Radix UI with accessible state management and keyboard support.

Usage

Basic Checkbox

import { Checkbox } from "@prisma-docs/eclipse";

export function BasicCheckbox() {
  return <Checkbox />;
}

Live Example:

With Label

Use labels to make checkboxes more accessible and user-friendly:

import { Checkbox } from "@prisma-docs/eclipse";

export function CheckboxWithLabel() {
  return (
    <div className="flex items-center gap-2">
      <Checkbox id="terms" />
      <label 
        htmlFor="terms" 
        className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
      >
        Accept terms and conditions
      </label>
    </div>
  );
}

Live Example:

With Field Component

Use the Field component for proper form structure with labels and descriptions:

import { Checkbox, Field, FieldLabel, FieldDescription } from "@prisma-docs/eclipse";

export function CheckboxWithField() {
  return (
    <Field orientation="horizontal" className="items-start">
      <Checkbox id="marketing" className="mt-0.5" />
      <div className="flex flex-col gap-1">
        <FieldLabel htmlFor="marketing">Marketing emails</FieldLabel>
        <FieldDescription>Receive emails about new products and features.</FieldDescription>
      </div>
    </Field>
  );
}

Live Example:

Receive emails about new products and features.

Controlled Checkbox

Control the checkbox state with React state:

import { Checkbox } from "@prisma-docs/eclipse";
import { useState } from "react";

export function ControlledCheckbox() {
  const [checked, setChecked] = useState(false);

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2">
        <Checkbox 
          id="controlled" 
          checked={checked}
          onCheckedChange={setChecked}
        />
        <label htmlFor="controlled" className="text-sm font-medium">
          Enable feature
        </label>
      </div>
      <p className="text-sm text-foreground-neutral-weak">
        Status: {checked ? "Enabled" : "Disabled"}
      </p>
    </div>
  );
}

Live Example:

Disabled State

import { Checkbox } from "@prisma-docs/eclipse";

export function DisabledCheckbox() {
  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2">
        <Checkbox id="disabled-unchecked" disabled />
        <label 
          htmlFor="disabled-unchecked" 
          className="text-sm font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
        >
          Disabled unchecked
        </label>
      </div>
      <div className="flex items-center gap-2">
        <Checkbox id="disabled-checked" disabled checked />
        <label 
          htmlFor="disabled-checked" 
          className="text-sm font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
        >
          Disabled checked
        </label>
      </div>
    </div>
  );
}

Live Example:

Checkbox Group

Create groups of related checkboxes:

import { Checkbox } from "@prisma-docs/eclipse";

export function CheckboxGroup() {
  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2 mb-2">
        <Checkbox id="notifications" defaultChecked />
        <label htmlFor="notifications" className="text-sm font-medium">Notifications</label>
      </div>
      <div className="flex items-center gap-2 mb-2">
        <Checkbox id="emails" />
        <label htmlFor="emails" className="text-sm font-medium">Email updates</label>
      </div>
      <div className="flex items-center gap-2 mb-2">
        <Checkbox id="sms" />
        <label htmlFor="sms" className="text-sm font-medium">SMS alerts</label>
      </div>
    </div>
  );
}

Live Example:

With Validation

Use with Field components for validation:

import { Checkbox, Field, FieldLabel, FieldDescription, FieldError } from "@prisma-docs/eclipse";

export function CheckboxWithValidation() {
  const [accepted, setAccepted] = useState(false);
  const [error, setError] = useState("");

  const handleSubmit = () => {
    if (!accepted) {
      setError("You must accept the terms and conditions");
    } else {
      setError("");
      // Continue with submission
    }
  };

  return (
    <div className="space-y-4">
      <Field orientation="horizontal" className="items-start">
        <Checkbox 
          id="terms-validation" 
          checked={accepted}
          onCheckedChange={setAccepted}
          className="mt-0.5"
        />
        <div className="flex flex-col gap-1">
          <FieldLabel htmlFor="terms-validation">I accept the terms and conditions</FieldLabel>
          <FieldDescription>You must accept to continue.</FieldDescription>
          {error && <FieldError>{error}</FieldError>}
        </div>
      </Field>
    </div>
  );
}

Live Example:

You must accept to continue.

In Forms

import { Checkbox, Button } from "@prisma-docs/eclipse";

export function CheckboxForm() {
  return (
    <form className="space-y-6 max-w-md">
      <div className="space-y-4">
        <h3 className="text-lg font-semibold">Privacy Settings</h3>
        
        <div className="flex items-center gap-2 mb-2">
          <Checkbox id="analytics" defaultChecked />
          <label htmlFor="analytics" className="text-sm font-medium">Allow analytics cookies</label>
        </div>
        
        <div className="flex items-center gap-2 mb-2">
          <Checkbox id="marketing-cookies" />
          <label htmlFor="marketing-cookies" className="text-sm font-medium">Allow marketing cookies</label>
        </div>
        
        <div className="flex items-center gap-2 mb-2">
          <Checkbox id="third-party" />
          <label htmlFor="third-party" className="text-sm font-medium">Allow third-party cookies</label>
        </div>
      </div>
      
      <Button type="submit">Save preferences</Button>
    </form>
  );
}

Live Example:

Privacy Settings

Component Props

Checkbox

The Checkbox component extends all Radix UI Checkbox props:

  • checked - Controlled checked state (boolean | "indeterminate", optional)
  • defaultChecked - Default checked state for uncontrolled usage (boolean, optional)
  • onCheckedChange - Callback when checked state changes (function, optional)
  • disabled - Whether the checkbox is disabled (boolean, default: false)
  • required - Whether the checkbox is required (boolean, default: false)
  • name - Name for form submission (string, optional)
  • value - Value for form submission (string, default: "on")
  • id - HTML id attribute (string, optional)
  • className - Additional CSS classes (string, optional)
  • All standard Radix UI Checkbox Root props

Features

  • ✅ Built on Radix UI for robust accessibility
  • ✅ Keyboard navigation support (Space to toggle)
  • ✅ Controlled and uncontrolled modes
  • ✅ Disabled state
  • ✅ Focus visible indicators
  • ✅ Checked state with animated icon
  • ✅ Works with forms and validation
  • ✅ Screen reader support
  • ✅ Customizable with className
  • ✅ Fully typed with TypeScript

Best Practices

  • Always pair checkboxes with labels for better UX and accessibility
  • Use htmlFor on labels to match checkbox id for clickable labels
  • Use Field components for forms with descriptions and errors
  • Group related checkboxes together visually
  • Use controlled state when you need to react to changes
  • Provide clear, concise label text
  • Use disabled state sparingly
  • Consider using FieldDescription for additional context
  • Test keyboard navigation (Tab, Space)
  • Ensure labels are clickable by using proper htmlFor attributes

Common Use Cases

The Checkbox component is perfect for:

  • Terms acceptance - Legal agreements and policies
  • Settings toggles - Enable/disable features
  • Multi-select lists - Selecting multiple items
  • Filters - Filtering content by categories
  • Permissions - Granting access rights
  • Preferences - User preferences and options
  • Task lists - To-do items and checklists
  • Consent forms - Privacy and cookie consent

Accessibility

The Checkbox component follows accessibility best practices:

  • Uses Radix UI's accessible checkbox primitive
  • Proper ARIA attributes (role="checkbox", aria-checked)
  • Keyboard accessible (Space to toggle, Tab to navigate)
  • Focus visible indicators
  • Screen reader support with proper labels
  • Disabled state prevents interaction
  • Works with form validation
  • Supports required attribute
  • Proper focus management
  • High contrast border and checked state

Keyboard Shortcuts

  • Space - Toggle checkbox on/off
  • Tab - Move focus to next element
  • Shift + Tab - Move focus to previous element

Styling

The Checkbox component uses design tokens:

  • Border: border-primary
  • Checked background: bg-primary
  • Checked color: text-primary-foreground
  • Focus ring: ring-ring
  • Size: 16×16px (h-4 w-4)
  • Border radius: rounded-sm
  • Check icon: Lucide Check icon

Customize by passing className:

<Checkbox className="border-2 border-blue-500 data-[state=checked]:bg-blue-500" />

Integration with Other Components

Checkbox works well with:

  • Field - Form structure with labels and descriptions
  • FieldLabel - Accessible labels
  • FieldDescription - Helper text
  • FieldError - Validation messages
  • Forms - Form submission and validation
  • Cards - Selection within cards
  • Lists - Multi-select lists
  • Tables - Row selection

Form Integration

The Checkbox component works seamlessly with forms:

<form onSubmit={handleSubmit}>
  <Checkbox name="terms" value="accepted" required />
  <button type="submit">Submit</button>
</form>

When checked, the form data will include: terms=accepted

On this page