|Design System

Core Component

Checkbox

Binary or tri-state checkbox with spring-animated check icon, label, and description.

Preview

Stream responses

Show AI responses as they generate

Enable tool use

Allow the model to call external tools

Select all

Locked setting

Source

Full component implementation using the design system tokens.

tsx
"use client";

import { useState } from "react";
import { Check, Minus } from "lucide-react";

export function DSCheckbox({
  checked: controlledChecked,
  defaultChecked = false,
  onChange,
  label,
  description,
  indeterminate = false,
  disabled = false,
}: {
  checked?: boolean;
  defaultChecked?: boolean;
  onChange?: (checked: boolean) => void;
  label?: string;
  description?: string;
  indeterminate?: boolean;
  disabled?: boolean;
}) {
  const [internalChecked, setInternalChecked] = useState(defaultChecked);
  const isControlled = controlledChecked !== undefined;
  const checked = isControlled ? controlledChecked : internalChecked;

  const toggle = () => {
    if (disabled) return;
    const next = !checked;
    if (!isControlled) setInternalChecked(next);
    onChange?.(next);
  };

  const isActive = checked || indeterminate;

  return (
    <div className="flex items-start gap-3">
      <button
        role="checkbox"
        aria-checked={indeterminate ? "mixed" : checked}
        onClick={toggle}
        disabled={disabled}
        className={`relative inline-flex items-center justify-center w-5 h-5 shrink-0 rounded-md border-2 transition-all duration-150 active:scale-[0.95] mt-0.5 ${isActive ? "bg-accent border-accent" : "border-overlay/15 hover:border-overlay/25"} ${disabled ? "opacity-50 cursor-not-allowed active:scale-100" : ""}`}
        style={{ transitionTimingFunction: "var(--ease-out)" }}
      >
        {indeterminate ? (
          <Minus className="w-3.5 h-3.5 text-background" />
        ) : (
          <Check className="w-3.5 h-3.5 text-background" style={{
            opacity: checked ? 1 : 0,
            transform: checked ? "scale(1)" : "scale(0.5)",
            transition: "opacity 150ms var(--ease-out), transform 200ms var(--ease-out)",
          }} />
        )}
      </button>
      {(label || description) && (
        <div className={disabled ? "opacity-50" : "cursor-pointer"} onClick={disabled ? undefined : toggle}>
          {label && <p className="text-sm font-medium text-foreground">{label}</p>}
          {description && <p className="text-xs text-tertiary mt-0.5">{description}</p>}
        </div>
      )}
    </div>
  );
}

Props

All available props with types and defaults.

PropTypeDescription
checkedbooleanControlled checked state
defaultCheckedbooleanInitial checked state (uncontrolled)
onChange(checked: boolean) => voidCalled when checked state changes
labelstringLabel text
descriptionstringHelper text below label
indeterminatebooleanShows minus icon for partial state
disabledbooleanDisables the checkbox

Variants

Default

Basic checkbox with label.

Enable streaming

tsx
<DSCheckbox label="Enable streaming" />

With Description

Checkbox with label and helper text.

Tool use

Allow the model to call external tools

tsx
<DSCheckbox label="Tool use" description="Allow the model to call external tools" />

Indeterminate

Partial selection state for parent checkboxes.

Select all

tsx
<DSCheckbox indeterminate label="Select all" />

Disabled

Non-interactive disabled state.

Locked setting

tsx
<DSCheckbox disabled label="Locked setting" />

Prompt Guide

Prompt Guide — Checkbox

Use for

  • Multi-select settings (enable tools, features)
  • Terms and conditions acceptance
  • Bulk selection with indeterminate parent
  • Filter toggles in search interfaces

Don't use for

  • Single on/off — use Toggle for binary switches
  • Mutually exclusive options — use Radio group
  • Momentary actions — use Button instead

AI Context

Check icon animates from scale(0.5) to scale(1) with opacity for a spring-like feel. The indeterminate state uses a Minus icon for 'select all' parent checkboxes. Supports both controlled and uncontrolled patterns.