NimUI
ComponentsPrimitives

Checkbox

Boolean selection control built on Radix UI

The Checkbox component is a boolean selection control built on Radix UI Checkbox. It provides accessible, keyboard-navigable checkboxes that work seamlessly with form patterns.

Import

import { Checkbox } from '@nim-ui/components';

Variants

Default

Default Checkbox
Code
<Checkbox id="default-check" label="Default checkbox" />

With Label Pattern

The recommended usage is to pass label directly. The component generates a comfortable option row and keeps the label associated with the control.

Checkbox with Labels
Code
<Checkbox id="terms" label="Accept terms and conditions" />
<Checkbox id="newsletter" label="Subscribe to newsletter" />
<Checkbox
  id="notifications"
  label="Enable notifications"
  description="Receive operational alerts for assigned queues."
/>

Sizes

Use size="sm" for dense lists and size="lg" when the checkbox sits in a prominent mobile or settings row.

Checkbox Sizes
Code
<Checkbox id="compact-check" size="sm" label="Compact row" />
<Checkbox id="default-size-check" size="md" label="Balanced row" />
<Checkbox id="large-check" size="lg" label="Prominent row" />

States

Disabled

Disabled State
Code
<Checkbox id="disabled-unchecked" disabled label="Disabled unchecked" />
<Checkbox id="disabled-checked" disabled checked label="Disabled checked" />

Props

NameTypeDefaultDescription
checkedboolean | "indeterminate"-Controlled checked state of the checkbox
onCheckedChange(checked: boolean | "indeterminate") => void-Callback fired when the checked state changes
defaultCheckedboolean-Initial checked state for uncontrolled usage
disabledbooleanfalseWhether the checkbox is disabled
idstring-HTML id attribute, used to associate with a label
labelReact.ReactNode-Visible label rendered with comfortable spacing from the checkbox
descriptionReact.ReactNode-Optional secondary copy linked through aria-describedby
size"sm" | "md" | "lg""md"Control size for denser or more prominent rows
wrapperClassNamestring-Additional classes for the generated checkbox row
classNamestring-Additional CSS classes to apply

Usage Examples

Terms Agreement

function TermsAgreement() {
  const [agreed, setAgreed] = useState(false);

  return (
    <div className="space-y-4">
      <Checkbox
        id="terms"
        checked={agreed}
        onCheckedChange={(checked) => setAgreed(checked === true)}
        label="I agree to the Terms of Service and Privacy Policy"
      />
      <Button disabled={!agreed}>Continue</Button>
    </div>
  );
}

Settings Panel

function NotificationSettings() {
  const [settings, setSettings] = useState({
    email: true,
    push: false,
    sms: false,
  });

  const toggle = (key: keyof typeof settings) => {
    setSettings((prev) => ({ ...prev, [key]: !prev[key] }));
  };

  return (
    <div className="space-y-3">
      <h3 className="text-lg font-semibold">Notifications</h3>
      <Checkbox
        id="email-notif"
        checked={settings.email}
        onCheckedChange={() => toggle('email')}
        label="Email notifications"
      />
      <Checkbox
        id="push-notif"
        checked={settings.push}
        onCheckedChange={() => toggle('push')}
        label="Push notifications"
      />
      <Checkbox
        id="sms-notif"
        checked={settings.sms}
        onCheckedChange={() => toggle('sms')}
        label="SMS notifications"
      />
    </div>
  );
}

Filter List

function CategoryFilter({ categories, selected, onChange }) {
  return (
    <div className="space-y-2">
      <h4 className="text-sm font-medium text-gray-700">Categories</h4>
      {categories.map((category) => (
        <Checkbox
          key={category.id}
          id={`cat-${category.id}`}
          checked={selected.includes(category.id)}
          label={category.name}
          onCheckedChange={(checked) => {
            if (checked) {
              onChange([...selected, category.id]);
            } else {
              onChange(selected.filter((id) => id !== category.id));
            }
          }}
        />
      ))}
    </div>
  );
}

Accessibility

The Checkbox component is built on Radix UI and follows WAI-ARIA best practices:

  • Uses role="checkbox" with proper aria-checked state
  • Supports aria-label and aria-labelledby for screen reader announcements
  • Full keyboard navigation support
  • Focus visible states for keyboard users
  • Disabled state properly communicated to assistive technology

Keyboard Support

KeyAction
SpaceToggles the checkbox
TabMoves focus to the next focusable element
Shift + TabMoves focus to the previous focusable element

Best Practices

  • Prefer the built-in label prop, or pair custom layouts with visible labels using id and htmlFor
  • Use aria-describedby to link additional descriptive text
  • Group related checkboxes with a heading or fieldset/legend
  • Avoid using checkboxes for actions; use a Switch for on/off toggles
  • Switch - Toggle switch for on/off states
  • Radio - Single selection from a group
  • Button - Interactive button for actions
  • Select - Dropdown selection input

On this page