Skip to content
quartiledocsv0.1
GitHub

Checkbox, Radio & Switch

Preview

Checkboxes pick several options, a radio group picks one, and a switch turns a setting on or off.

Example

const CHANNELS = ['Organic search', 'Paid social', 'Email', 'Direct'];
const [channels, setChannels] = useState(['Email', 'Direct']);
const all = channels.length === CHANNELS.length;

<Checkbox
  label="All channels"
  checked={all}
  indeterminate={channels.length > 0 && !all}
  onChange={(on) => setChannels(on ? CHANNELS : [])}
/>
{CHANNELS.map((c) => (
  <Checkbox
    key={c}
    label={c}
    checked={channels.includes(c)}
    onChange={(on) => setChannels(on ? [...channels, c] : channels.filter((x) => x !== c))}
  />
))}

<RadioGroup aria-label="Aggregation" options={['Sum', 'Average', 'Median']} defaultValue="Sum" />
<Switch label="Compare to previous period" defaultChecked showState />
<Switch label="Email me when this report changes" description="Sent at most once a day." size="sm" />

Usage

All three are controlled (checked or value with onChange) or uncontrolled (defaultChecked or defaultValue). onChange receives the new boolean or value, not an event.

indeterminate is controlled: the checkbox shows a dash for as long as you pass true. Clear it in onChange, or derive it from state as above.

RadioGroup takes options (strings or { value, label, description }), or compose <Radio> children yourself.

Props

Checkbox

PropTypeDefaultDescription
checkedboolean——
defaultCheckedbooleanfalse—
indeterminatebooleanfalseMixed state, e.g. a "select all" when some rows are selected. Shows a dash. Controlled: clear it in onChange.
onChange(checked: boolean) => void——
labelReactNode——
descriptionReactNode—Second line under the label.

Also accepts the props of Omit< InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'onChange' | 'checked' | 'defaultChecked' >, spread onto the root element.

RadioGroup

PropTypeDefaultDescription
options(string | RadioOption)[]—Strings are used as both value and label. Omit to compose <Radio> children instead.
valuestring | null——
defaultValuestring | nullnull—
onChange(value: string) => void——
namestring—Form name shared by the radios. Generated when omitted.
orientation'horizontal' | 'vertical''horizontal'—
disabledboolean——
classNamestring——
styleCSSProperties——
childrenReactNode——
aria-labelstring——
aria-labelledbystring——

RadioOption

PropTypeDefaultDescription
valuerequiredstring——
labelrequiredReactNode——
descriptionReactNode——
disabledboolean——

Switch

PropTypeDefaultDescription
checkedboolean——
defaultCheckedbooleanfalse—
onChange(checked: boolean) => void——
labelReactNode——
descriptionReactNode—Second line under the label.
size'sm' | 'md''md'sm: 28 × 16 track · md: 32 × 18.
showStatebooleanfalseShows "On" / "Off" in mono after the label.

Also accepts the props of Omit< InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'onChange' | 'checked' | 'defaultChecked' | 'role' >, spread onto the root element.

Accessibility

  • Native inputs with their labels attached; Space toggles a checkbox or switch.
  • The indeterminate checkbox reports the mixed state to assistive technology.
  • RadioGroup is a native radio group: arrow keys move and select. Name it with aria-label or aria-labelledby.
  • Switch is an input with the switch role.
Report an issueBuilt Oct 21, 2026