Skip to content

Checkbox

Checkbox represents an independent boolean choice. It works for agreements, settings, row selection, and mixed selection summaries.

Checkbox states Open in Storybook

When To Use

Use Checkbox when each option can be turned on or off without requiring another option to turn off. Use RadioGroup when exactly one option must be selected. Use Button for commands and Toggle-like buttons for transient pressed state.

tsx
<Checkbox
  checked={accepted}
  onCheckedChange={setAccepted}
  color='primary'
  size='md'
  label='Accept terms'
  description='Required before creating the workspace.'
/>

API Shape

Use checked with onCheckedChange for controlled state, or defaultChecked for uncontrolled state. color changes the selected intent, while labelPosition controls whether the visible label sits before or after the checkbox.

tsx
<Checkbox
  checked={enabled}
  onCheckedChange={setEnabled}
  color='success'
  labelPosition='start'
  label='Enable automation'
  description='Runs workspace rules when new records arrive.'
/>

Use icon and indeterminateIcon only when the default checkmark or mixed mark does not match the surrounding product language.

tsx
<Checkbox
  defaultChecked
  icon={<span aria-hidden='true'>✓</span>}
  indeterminateIcon={<span aria-hidden='true'>−</span>}
  label='Custom indicator'
/>

Props

PropPurpose
checkedControlled checked state.
defaultCheckedInitial checked state for uncontrolled use.
onCheckedChangeReceives the next boolean checked state.
sizesm, md, or lg.
colorprimary, neutral, success, warning, or danger.
labelVisible label text or content.
descriptionHelper text rendered below the row.
errorValidation message and invalid state.
requiredMarks the input as required.
disabledPrevents interaction.
indeterminateShows and announces a mixed state.
labelPositionend or start.
iconCustom checked-state icon.
indeterminateIconCustom mixed-state icon.
classNameRoot class name on web.
wrapperClassNameClickable row class name on web.

Common Patterns

Settings Row

tsx
<Checkbox
  defaultChecked
  label='Email product updates'
  description='Receive important release and billing updates.'
/>

Mixed Selection

Use indeterminate when a parent row represents a partial child selection.

tsx
<Checkbox
  checked={allSelected}
  indeterminate={someSelected && !allSelected}
  onCheckedChange={toggleAll}
  label='Select all projects'
/>

Error State

tsx
<Checkbox
  required
  checked={accepted}
  onCheckedChange={setAccepted}
  label='I accept the data processing agreement'
  error='Accept the agreement to continue.'
/>

Real Example: Notification Preferences

tsx
import { Button, Checkbox } from '@vellira-ui/react';
import { useState } from 'react';

export function NotificationPreferences() {
  const [security, setSecurity] = useState(true);
  const [product, setProduct] = useState(false);
  const [billing, setBilling] = useState(true);

  return (
    <form onSubmit={savePreferences}>
      <Checkbox
        checked={security}
        onCheckedChange={setSecurity}
        label='Security alerts'
        description='Required for sign-in, password, and permission changes.'
        disabled
      />
      <Checkbox
        checked={billing}
        onCheckedChange={setBilling}
        label='Billing updates'
        description='Invoices, payment failures, and plan changes.'
      />
      <Checkbox
        checked={product}
        onCheckedChange={setProduct}
        label='Product updates'
        description='New components, migration notes, and release summaries.'
      />
      <Button type='submit'>Save preferences</Button>
    </form>
  );
}

Accessibility

  • Keep the label close to the control and make it descriptive.
  • Use description for durable context, not hover-only help.
  • When no visible label is rendered, provide aria-label on web or accessibilityLabel on native.
  • Do not use indeterminate as a third submitted value. It is a visual and accessibility state for partial selection.

See Also

Built for Vellira Design System.