Checkbox

Checkboxes allow users to select one or more items from a set of options or to toggle a single setting on or off.

Overview

The Checkbox component provides a standard form control for binary or tri-state selections. It supports checked, unchecked, and indeterminate states, with built-in accessibility and keyboard navigation.

tsx
import { Checkbox } from "@rogo-technologies/ui/checkbox"

<Checkbox id="newsletter" />
<label htmlFor="newsletter">Subscribe to newsletter</label>

Basic

A simple checkbox with a label. Use Checkbox for the standard checkbox implementation with automatic indicator handling.

tsx
<div className="flex items-center gap-1">
  <Checkbox id="terms" />
  <label htmlFor="terms">Accept terms and conditions</label>
</div>

States

Use the checked prop to control the checkbox state. Supports true, false, and "mixed" (or "indeterminate") for tri-state selections.

StateValueUse Case
UncheckedfalseOption is not selected
CheckedtrueOption is selected
Mixed"mixed" or "indeterminate"Parent checkbox when some children are selected
tsx
// Uncontrolled (manages own state)
<Checkbox id="option" />

// Controlled states
<Checkbox checked={false} />  // Unchecked
<Checkbox checked={true} />   // Checked
<Checkbox checked="mixed" />  // Indeterminate

// Both "mixed" and "indeterminate" are supported
<Checkbox checked="indeterminate" />

Controlled Checkbox

Use checked and onCheckedChange for controlled checkbox state.

tsx
const [isChecked, setIsChecked] = useState(false)

<Checkbox
  checked={isChecked}
  onCheckedChange={(checked) => setIsChecked(checked)}
/>

Disabled

Use the disabled prop to prevent interaction when the option is unavailable.

tsx
// Disabled states
<Checkbox disabled />
<Checkbox checked disabled />

// Remember to style the label to match
<div className="flex items-center gap-1">
  <Checkbox id="disabled" disabled />
  <label htmlFor="disabled" className="opacity-50">
    Unavailable option
  </label>
</div>

Interactive

An interactive example demonstrating controlled checkbox state.

tsx
const [checked, setChecked] = useState(false)

<Checkbox
  id="interactive"
  checked={checked}
  onCheckedChange={setChecked}
/>
<label htmlFor="interactive">
  {checked ? "Checked" : "Unchecked"}
</label>

Checkbox Groups

Use multiple checkboxes for selecting from a set of options. For "select all" functionality, use the mixed state.

tsx
const [selectedItems, setSelectedItems] = useState<string[]>([])
const allItems = ["Option 1", "Option 2", "Option 3"]

const allSelected = selectedItems.length === allItems.length
const someSelected = selectedItems.length > 0 && !allSelected

<Checkbox
  checked={allSelected ? true : someSelected ? "mixed" : false}
  onCheckedChange={(checked) => {
    setSelectedItems(checked ? allItems : [])
  }}
/>
<label>Select all</label>

{allItems.map((item) => (
  <Checkbox
    key={item}
    checked={selectedItems.includes(item)}
    onCheckedChange={(checked) => {
      setSelectedItems(prev =>
        checked ? [...prev, item] : prev.filter(i => i !== item)
      )
    }}
  />
))}

Composable API

Use CheckboxRoot and CheckboxIndicator for custom checkbox implementations with full control over the indicator content.

tsx
import { CheckboxRoot, CheckboxIndicator } from "@rogo-technologies/ui/checkbox"

// Default indicator (checkmark icon)
<CheckboxRoot id="option">
  <CheckboxIndicator />
</CheckboxRoot>

// Custom indicator content
<CheckboxRoot id="option">
  <CheckboxIndicator>
    <span className="text-xs"></span>
  </CheckboxIndicator>
</CheckboxRoot>

// Custom indicator with icon
<CheckboxRoot id="option">
  <CheckboxIndicator>
    <IconStar className="size-3" />
  </CheckboxIndicator>
</CheckboxRoot>

With Form Libraries

The checkbox works with form libraries like React Hook Form.

tsx
import { useForm } from "react-hook-form"

const { register, handleSubmit } = useForm()

<form onSubmit={handleSubmit(onSubmit)}>
  <Checkbox {...register("acceptTerms")} />
  <label>Accept terms and conditions</label>
</form>

Props

Checkbox

The standard checkbox component with built-in indicator handling.

PropTypeDefaultDescription
checkedboolean | "mixed" | "indeterminate"Controlled checked state.
defaultCheckedbooleanfalseInitial checked state for uncontrolled usage.
onCheckedChange(checked: boolean) => voidCallback when checked state changes.
disabledbooleanfalseDisables the checkbox.
requiredbooleanfalseMarks the checkbox as required.
namestringName attribute for form submission.
valuestring"on"Value attribute for form submission.

CheckboxRoot

The base checkbox component for custom implementations.

PropTypeDefaultDescription
checkedbooleanControlled checked state.
defaultCheckedbooleanfalseInitial checked state.
onCheckedChange(checked: boolean) => voidCallback when checked state changes.
disabledbooleanfalseDisables the checkbox.

CheckboxIndicator

The indicator shown when the checkbox is checked.

PropTypeDefaultDescription
childrenReactNodeCheckmark iconCustom indicator content.

Accessibility

  • Checkbox is keyboard accessible with Space to toggle
  • Focus is visible with a ring indicator
  • Associates with labels via id and htmlFor
  • Supports aria-describedby for additional descriptions
  • Mixed state is announced to screen readers
tsx
// Proper labeling
<Checkbox id="option" aria-describedby="option-description" />
<label htmlFor="option">Enable notifications</label>
<p id="option-description">You'll receive email alerts for new messages.</p>

Usage Guidelines

Do

  • Always pair checkboxes with visible labels
  • Use the mixed state for "select all" checkboxes when some items are selected
  • Group related checkboxes together visually
  • Use checkboxes for independent options that can all be selected
  • Provide clear, concise labels that describe what selecting the checkbox does

Don't

  • Don't use checkboxes for mutually exclusive options—use radio buttons instead
  • Don't use a checkbox for a single binary action—consider a switch/toggle instead
  • Don't disable checkboxes without explanation—provide context via tooltip or helper text
  • Don't use negative labels ("Don't send emails")—use positive phrasing ("Send emails")
  • Don't nest checkboxes more than one level deep for "select all" patterns
© 2026 Rogo Technologies Inc.