Checkbox

Zero or more choices out of a set, each independent. The indeterminate state is a parent's summary of its children, not a third value.

Usage

When to reach for Checkbox, how single boxes and groups differ, and how to wire them into a form.

When to use

A checkbox is a choice the reader turns on or off, alone or as one of several independent options. Nothing takes effect until something else submits.
  • A set of options where any number can be on: which notifications to send, which columns to export.
  • One box for a yes or no the form carries: accept the terms, remember this device.
  • A selectable list or table, where the header box sums up the rows.
  • A tree, where a parent box reports what its children add up to.
Reach for something else when:
  • Switch when the change takes effect as soon as it is made. A checkbox that saves on click looks like one that waits.
  • Radio.Group when only one option can be picked.
  • Select with mode="multiple" when the list is long, searched or loaded.

One box, or a Group

A single Checkbox holds a boolean and reports e.target.checked. Checkbox.Group holds an array and calls onChange(checkedValues) with it. Use a group instead of a boolean per option.
  • value belongs to a group. On a single box, use checked, or antd warns.
  • Give Checkbox.Group its value type. With Checkbox.Group<Fruit>, options, value and onChange share one type. It is not inferred from an array of strings, so write it out.
  • When options is set, children are ignored. Use one or the other.
  • onChange lists values in option order, not click order, so its last item is not always the latest click.
  • A box inside a group gets its name and checked from the group, so do not control it again. skipGroup leaves a box out of the group's value.

Indeterminate is a summary, not a value

indeterminate only changes the look. It draws a partly checked box, and checked still decides the value. A box can be both, and it submits as checked.
  • Set it from a count: checked when every child is on, indeterminate when some are. Do not store it in its own state.
  • Checkbox.Group has no indeterminate, so a select-all box is a separate Checkbox beside the group.
  • Clicking the parent checks or clears all its children.
  • Do not use it for “unknown” or “still loading”. It means some children are on.

Controlled or uncontrolled

Pick one per box and keep it. A checked that starts undefined and later becomes a boolean takes over the box with no warning.
  • Uncontrolled is defaultChecked on a box or defaultValue on a group, and suits a form nothing else reacts to.
  • Controlled is checked with onChange, or a group's value with onChange, for when something else depends on the answer.
  • checked without onChange freezes the box. It looks broken, not disabled.

Labels, layout and the click target

The children are the label, and they sit inside the same <label> as the box, so clicking the text checks it with no htmlFor or id.
  • A checkbox with no children has only the small box to click and nothing for a screen reader to read. See the Accessibility tab.
  • Write the label for the checked state: “Send me product updates”, not “Do not send me product updates”.
  • One line, sentence case, no full stop. Put help text under the label, since everything inside it is read as the name.
  • Align the box with a two-line label. The box centers on the whole label. For a title with help text under it, move the box to the first line, as the With description example does.
  • Keep the options parallel, in an order the reader can predict, and do not reorder them on click.
  • Stack a group with flex classes. Checkbox.Group has no vertical prop. Use className="flex flex-col gap-xs". Rendering it through <Flex component={Checkbox.Group}> loses its value type. Stack as soon as labels run past three words.

Disabled

A box's own disabled wins, then the group's, then one set by a Form or ConfigProvider.
  • Disable the options that do not apply, not the whole group. Tab skips a disabled box, so the reader cannot land on it.
  • An option object in options takes its own disabled.
  • Say why in text nearby: “Included in your plan”, “Requires an admin”.
  • Do not use disabled for read-only. Show a fixed answer as text.

Inside a Form

In a form, set valuePropName="checked". A single checkbox reports checked, not value, so its Form.Item needs valuePropName="checked". A Checkbox.Group needs nothing extra.
  • Without it the box never moves and antd warns about value.
  • For a box the reader must check, add a rule whose validator rejects false. required does not do it, because the field is always present.
  • A group is one field, so show one error under the whole group.
  • To restyle only checkboxes inside forms, target ant-checkbox-wrapper-in-form-item.