checkbox
A control that allows the user to toggle between checked and not checked.
Philosophy
Checkboxes are deceptively complex. A simple checked/unchecked state becomes indeterminate for parent/child relationships, needs accessible labels, and must work in both controlled and uncontrolled modes. We handle all of this with native checkbox semantics and custom SVG indicators, so the visual design is yours while the behavior is correct.
How It's Built
Installation
npx @gentleduck/cli add checkbox
npx @gentleduck/cli add checkbox
Usage
import { Checkbox } from "@/components/ui/checkbox"import { Checkbox } from "@/components/ui/checkbox"<Checkbox /><Checkbox />Examples
Basic uncontrolled checkbox
Controlled checkbox
Checkbox with label
Indeterminate state
Checkbox group
Custom indicator icons
Form
Component Composition
API Reference
Checkbox
| Prop | Type | Default | Description |
|---|---|---|---|
indicator | React.ReactElement | -- | Custom SVG or icon for unchecked state indicator |
checkedIndicator | React.ReactElement | -- | Custom SVG or icon for checked state indicator |
checked | boolean | 'indeterminate' | -- | Controlled checked state |
defaultChecked | boolean | 'indeterminate' | false | Initial checked state if uncontrolled |
onCheckedChange | (checked: boolean | 'indeterminate') => void | -- | Callback fired when checked state changes |
dir | 'ltr' | 'rtl' | -- | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr'). |
className | string | -- | Additional CSS classes applied to the checkbox input |
style | React.CSSProperties | -- | Inline styles merged with internal indicator styles |
ref | React.Ref<HTMLInputElement> | -- | Ref forwarded to the native checkbox input |
...props | Omit<React.HTMLProps<HTMLInputElement>, 'checked' | 'onChange' | 'defaultChecked'> | -- | Additional props to spread to the input element |
CheckboxWithLabel
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | (required) | HTML id attribute to link checkbox and label |
_checkbox | React.ComponentPropsWithoutRef<typeof Checkbox> | (required) | Props passed to the internal Checkbox component |
_label | React.ComponentPropsWithoutRef<typeof Label> | (required) | Props passed to the internal Label component |
className | string | -- | Additional CSS classes applied to the wrapping div |
ref | React.Ref<HTMLDivElement> | -- | Ref forwarded to the wrapping div |
...props | React.HTMLProps<HTMLDivElement> | -- | Additional props to spread to the content div |
CheckboxGroup
| Prop | Type | Default | Description |
|---|---|---|---|
subtasks | CheckboxGroupSubtasks[] | (required) | Array of subtasks to render as individual checkboxes with labels |
subtasks_default_values | CheckboxWithLabelProps | -- | Default props applied to each checkbox and label in the group |
className | string | -- | Additional CSS classes applied to the wrapping div |
ref | React.Ref<HTMLDivElement> | -- | Ref forwarded to the wrapping div |
...props | React.HTMLProps<HTMLDivElement> | -- | Additional props to spread to the content div |
CheckboxGroupSubtasks
type CheckboxGroupSubtasks = {
id: string
title: string
checked?: boolean | 'indeterminate'
}type CheckboxGroupSubtasks = {
id: string
title: string
checked?: boolean | 'indeterminate'
}RTL Support
Direction is resolved through the shared primitives direction module. Use a local dir="rtl" override when the component exposes it, or set DirectionProvider at app/root level for global RTL/LTR behavior.
See also
- Radio Group — Single selection from a set of options
- Switch — Toggle between on and off states