Skip to content

Checkbox

Checkbox and CheckboxGroup work together to build checkbox form fields.
Figma logo
  • CheckboxGroup is a field element that wraps checkboxes with label, helper, and validation text.
  • Validation text must be added separately when using Checkbox on its own (example).
Switch
  • Switch reflects a boolean state (enabled/disabled, on/off)
  • Switch has a more approachable UI that users may associate with an immediate response
Checkbox
  • A single Checkbox should be used when agreeing/acknowledging/accepting terms/policies, etc.
  • Typically associated with a form that must be submitted for changes to be saved/reflected
  • Checkbox is used when multiple items can be selected
  • Only used to change settings, not as a trigger
    • Use Button if you need to perform an action
Radio
  • Use Radio if you need to toggle between two non-binary options (e.g. CSV/PDF, %/$)
  • Typically associated with a form that must be submitted for changes to be saved/reflected
  • Radio is used when the options are mutually exclusive
  • Only used to change settings, not as a trigger
    • Use Button if you need to perform an action

A basic CheckboxGroup implementation using Formik and Yup to require the field.

A CheckboxGroup implementation using Formik and Yup to require at least one box be selected. Child content is treated as helper text.

This example illustrates using Checkbox without CheckboxGroup. This method is far more laborious as validation text must be added manually.

A checkbox can have an indeterminate state when its value cannot be expressed with a binary true or false value. This state is most often used on groups of checkboxes that contain “children” elements, which can have different values.

Disabled states should be used with caution.

It may sometimes be necessary to hide labels, but label text must still be made available for screen readers. This example uses visuallyHidden to visually hide the label.

React props
NameTypeDefaultDescription
children  Required
ReactNode
-The individual Checkbox elements that are part of the group.
disabled  
boolean
-If true, the elements in this group will be shown in their disabled state.
helperText  
ReactNode
-Additional descriptive information for the checkboxes.
invalid  
boolean
-If true, the checkboxes will be shown in their invalid state.
legend  Required
string
-Label text associated with the group.
name  
string
-Name of the input. Submitted with the form as part of a name/value pair.
optional  
boolean
-Used to indicate the field is optional
validationText  
ReactNode
-Validation message associated with the input.
React props
NameTypeDefaultDescription
children  
ReactNode
-Content will be treated as helper text.
component  
ReactNode
-Component override for the <input> element.
indeterminate  
boolean
-If true, the checkbox will be displayed in an indeterminate state.
label  Required
string
-Label text associated with the input.
value  Required
string
-The data value of the input.

The following testing snippet(s) offer suggestions for testing the component using React Testing LibraryExternal link with occasional help from JestExternal link.

render(
<CheckboxGroup
name="notifications"
legend="Enable notifications?"
helperText="How much would you like to hear from us?"
optional
>
<Checkbox label="Alerts" value="alerts">
Alerts are like really really important things that we only tell you about when the world is
ending.
</Checkbox>
<Checkbox label="Newsletter" value="newsletter">
This is pretty much just everything else.
</Checkbox>
</CheckboxGroup>,
);
const group = screen.getByRole('group', {
name: 'Enable notifications?', // Group label
});
// Group descriptions
expect(group).toHaveAccessibleDescription(expect.stringContaining('(optional)'));
expect(group).toHaveAccessibleDescription(
expect.stringContaining('How much would you like to hear from us?'),
);
const alertsCheckbox = screen.getByLabelText('Alerts');
// Alternatively:
// const alertsCheckbox = screen.getByRole('checkbox', {
// name: 'Alerts',
// });
// Checkbox description
expect(alertsCheckbox).not.toBeChecked();
expect(alertsCheckbox).toHaveAccessibleDescription(
'Alerts are like really really important things that we only tell you about when the world is ending.',
);
const newsletterCheckbox = screen.getByLabelText('Newsletter');
// Checkbox description
expect(newsletterCheckbox).not.toBeChecked();
expect(newsletterCheckbox).toHaveAccessibleDescription('This is pretty much just everything else.');
// Checking
userEvent.click(alertsCheckbox);
expect(alertsCheckbox).toBeChecked();
// Testing validation
render(
<CheckboxGroup
name="notifications"
legend="Enable notifications?"
invalid
validationText="At least one selection is required"
>
<Checkbox label="Alerts" value="alerts" />
<Checkbox label="Newsletter" value="newsletter" />
</CheckboxGroup>,
);
const group = screen.getByRole('group', {
name: 'Enable notifications?', // Group label
});
expect(group).toHaveAccessibleDescription(
expect.stringContaining('At least one selection is required'),
);