Skip to main content

Overview

The Checkbox component provides an accessible checkbox with support for three states (unchecked, checked, indeterminate), multiple sizes, and optional descriptions. Built on React Aria Components for full keyboard navigation and screen reader support.

Import

import { Checkbox } from 'stride-ds';

Basic Usage

import { Checkbox } from 'stride-ds';

function Example() {
  return <Checkbox>Accept terms and conditions</Checkbox>;
}

Sizes

Three size options are available:
<Checkbox size="sm">Small checkbox</Checkbox>
<Checkbox size="md">Medium checkbox</Checkbox>
<Checkbox size="lg">Large checkbox</Checkbox>

With Description

Add supporting text below the main label:
<Checkbox 
  description="Get notified when someone mentions you in a comment or assigns you a task."
>
  Enable notifications
</Checkbox>

States

Checked

<Checkbox isSelected>Checked</Checkbox>

Indeterminate

Useful for “select all” functionality:
<Checkbox isIndeterminate>Indeterminate</Checkbox>

Disabled

<Checkbox isDisabled>Disabled</Checkbox>
<Checkbox isSelected isDisabled>Disabled & Checked</Checkbox>

Props

size
'sm' | 'md' | 'lg'
default:"'md'"
Size of the checkbox.
children
React.ReactNode
The label text for the checkbox.
description
React.ReactNode
Additional description text displayed below the label.
isSelected
boolean
default:"false"
Whether the checkbox is checked (controlled).
defaultSelected
boolean
default:"false"
Whether the checkbox is initially checked (uncontrolled).
isIndeterminate
boolean
default:"false"
Whether the checkbox is in an indeterminate state.
isDisabled
boolean
default:"false"
Whether the checkbox is disabled.
onChange
(isSelected: boolean) => void
Handler called when the checkbox state changes.
className
string
Additional CSS classes to apply.
value
string
The value of the checkbox in a form.
name
string
The name of the checkbox in a form.

Accessibility

The Checkbox component is built with React Aria Components and provides:
  • Keyboard Navigation: Space to toggle, Tab to move focus
  • Focus Management: Clear focus indicators
  • Screen Reader Support: Proper ARIA attributes including aria-checked and support for indeterminate state
  • Label Association: Automatic association between checkbox and label

Best Practices

  1. Always provide a label via children or use aria-label for accessibility:
    <Checkbox>Enable feature</Checkbox>
    // or
    <Checkbox aria-label="Enable feature" />
    
  2. Use description for additional context:
    <Checkbox description="This will enable advanced features">
      Enable advanced mode
    </Checkbox>
    
  3. Use indeterminate state for nested selections:
    <Checkbox isIndeterminate>Some items selected</Checkbox>
    

Examples

All States

<div className="flex flex-col space-y-4">
  <Checkbox>Unchecked</Checkbox>
  <Checkbox isSelected>Checked</Checkbox>
  <Checkbox isIndeterminate>Indeterminate</Checkbox>
  <Checkbox isDisabled>Disabled</Checkbox>
  <Checkbox isSelected isDisabled>Disabled & Checked</Checkbox>
</div>

Indeterminate with “Select All”

import { useState } from 'react';
import { Checkbox } from 'stride-ds';

function SelectAllExample() {
  const [child1, setChild1] = useState(false);
  const [child2, setChild2] = useState(true);
  const [child3, setChild3] = useState(false);

  const childrenStates = [child1, child2, child3];
  const allChecked = childrenStates.every(Boolean);
  const someChecked = childrenStates.some(Boolean);
  const isIndeterminate = someChecked && !allChecked;

  const handleParentChange = (checked: boolean) => {
    setChild1(checked);
    setChild2(checked);
    setChild3(checked);
  };

  return (
    <div className="flex flex-col space-y-3">
      <Checkbox
        isSelected={allChecked}
        isIndeterminate={isIndeterminate}
        onChange={handleParentChange}
      >
        Select all
      </Checkbox>

      <div className="ml-6 flex flex-col space-y-2">
        <Checkbox isSelected={child1} onChange={setChild1}>
          Option 1
        </Checkbox>
        <Checkbox isSelected={child2} onChange={setChild2}>
          Option 2
        </Checkbox>
        <Checkbox isSelected={child3} onChange={setChild3}>
          Option 3
        </Checkbox>
      </div>
    </div>
  );
}

Form Integration

import { useState } from 'react';
import { Checkbox } from 'stride-ds';

function NewsletterForm() {
  const [preferences, setPreferences] = useState({
    newsletter: false,
    updates: false,
    marketing: false,
  });

  return (
    <div className="space-y-4">
      <h3 className="font-semibold">Email Preferences</h3>
      
      <Checkbox
        isSelected={preferences.newsletter}
        onChange={(checked) => 
          setPreferences({ ...preferences, newsletter: checked })
        }
        description="Receive our weekly newsletter with the latest updates"
      >
        Newsletter
      </Checkbox>

      <Checkbox
        isSelected={preferences.updates}
        onChange={(checked) => 
          setPreferences({ ...preferences, updates: checked })
        }
        description="Get notified about product updates and new features"
      >
        Product Updates
      </Checkbox>

      <Checkbox
        isSelected={preferences.marketing}
        onChange={(checked) => 
          setPreferences({ ...preferences, marketing: checked })
        }
        description="Receive promotional offers and marketing emails"
      >
        Marketing Emails
      </Checkbox>
    </div>
  );
}

All Sizes Comparison

<div className="flex flex-col space-y-4">
  <Checkbox size="sm">Small checkbox with text</Checkbox>
  <Checkbox size="md">Medium checkbox with text</Checkbox>
  <Checkbox size="lg">Large checkbox with text</Checkbox>
</div>

With Long Content

<Checkbox 
  description="By checking this box, you acknowledge that you have read and agree to our Terms of Service and Privacy Policy. This includes how we collect, use, and share your data."
>
  I agree to the Terms of Service and Privacy Policy
</Checkbox>

React Hook Form Integration

The Checkbox component works with React Hook Form:
import { useForm, Controller } from 'react-hook-form';
import { Checkbox } from 'stride-ds';

function FormExample() {
  const { control, handleSubmit } = useForm();

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="terms"
        control={control}
        rules={{ required: 'You must accept the terms' }}
        render={({ field }) => (
          <Checkbox
            isSelected={field.value}
            onChange={field.onChange}
          >
            I accept the terms and conditions
          </Checkbox>
        )}
      />
    </form>
  );
}

Build docs developers (and LLMs) love