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.
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.
<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.
| State | Value | Use Case |
|---|---|---|
| Unchecked | false | Option is not selected |
| Checked | true | Option is selected |
| Mixed | "mixed" or "indeterminate" | Parent checkbox when some children are selected |
// 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.
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.
// 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.
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.
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.
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.
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.
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | "mixed" | "indeterminate" | — | Controlled checked state. |
defaultChecked | boolean | false | Initial checked state for uncontrolled usage. |
onCheckedChange | (checked: boolean) => void | — | Callback when checked state changes. |
disabled | boolean | false | Disables the checkbox. |
required | boolean | false | Marks the checkbox as required. |
name | string | — | Name attribute for form submission. |
value | string | "on" | Value attribute for form submission. |
CheckboxRoot
The base checkbox component for custom implementations.
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | Controlled checked state. |
defaultChecked | boolean | false | Initial checked state. |
onCheckedChange | (checked: boolean) => void | — | Callback when checked state changes. |
disabled | boolean | false | Disables the checkbox. |
CheckboxIndicator
The indicator shown when the checkbox is checked.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Checkmark icon | Custom indicator content. |
Accessibility
- Checkbox is keyboard accessible with
Spaceto toggle - Focus is visible with a ring indicator
- Associates with labels via
idandhtmlFor - Supports
aria-describedbyfor additional descriptions - Mixed state is announced to screen readers
// 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