Checkbox is used for multiple choice selection. They are independent of each other in a list, and therefore, different from RadioButton, one selection does not affect other checkboxes in the same list.

Figma:

Responsive:

Adaptive:

Props

Component props
Name
Type
Default
id
Required
string
-

A unique identifier for the input.

onChange
Required
(arg1: { event: React.ChangeEvent<HTMLInputElement>; checked: boolean }) => void
-

Callback triggered when the state of the input changes.

checked
boolean
false

Indicates whether or not Checkbox is checked. See the state variant to learn more.

disabled
boolean
false

Indicates whether or not Checkbox is disabled. Disabled Checkboxes do not respond to mouse events and cannot be reached by the keyboard. See the state variant to learn more.

errorMessage
string
-

Displays an error message and error state. See the accessibility section to learn more.

helperText
string
-

Optional description for Checkbox, used to provide more detail about an option. See the with helperText variant to learn more.

image
React.Node
-

An optional Image can be supplied to add an image to each Checkbox. See the with Image variant to learn more.

indeterminate
boolean
false

Indicates a state that is neither checked nor unchecked. See the state variant to learn more.

label
string
-

The label for the input. Be sure to localize the text. See the accessibility section to learn more.

labelDisplay
"visible" | "hidden"
"visible"

Whether the label should be visible or not. If hidden, the label is still available for screen reader users, but does not appear visually. See the label visibility variant for more info.

name
string
-

A unique name for the input used to reference form data after it’s submitted. If the name attribute is not specified then the data of the checkbox would not be sent in the form submission.

onClick
(arg1: { event: React.ChangeEvent<HTMLInputElement>; checked: boolean }) => void
-

Callback triggered when the user clicks on the input.

ref
ReactElement
-

Ref that is forwarded to the underlying input element.

size
"sm" | "md"
"md"

Determines the Checkbox size: sm = 16px, md = 24px. See the size variant to learn more.

Usage guidelines

When to use
  • In a list, form or a Table, to present users with multiple, related options where more than one option can be selected. Users must be able to select all, none or some of the presented options.
  • In a Form, along with a TextField, or other spaces that are too small for a Switch
  • When selection doesn’t take immediate effect and requires form submission
When not to use
  • Situations where users can only choose one out of multiple, related options. Use RadioGroup instead.
  • When a selection takes immediate effect, especially on mobile. Use Switch instead.
  • When visually, it’s hard to tell that a checkbox turns something on or off. Use Switch instead.

Best practices

Do

Use checkboxes for multi-selection of related list items

Don't

Use checkboxes for one selection. Use RadioGroup instead.

Do

Use a single Checkbox in forms where the selection only takes effect after submitting the form

Don't

Use a Checkbox to turn a state on and off with immediate effect. Use Switch instead.

Do

Keep labels and legends clear and brief to avoid too many lines of text that are hard to scan and slow the user down. If clarification is needed, use info Tooltips or helperText.

Don't

Use lengthy text that truncates and doesn’t offer clear instructions for what you are expected to select

Do

Use Checkbox at the start of a table row to make it clear which rows are multi-selectable

Don't

Use numerous checkboxes in table rows that make it hard to tell what items apply to multi-select actions

Do

Use vertical alignment of multi-line labels so that the first line is vertically centered with the checkbox input

Don't

Vertically center checkbox inputs with their respective custom labels

Accessibility

Labels

Checkboxes should have labels that can be read by screen readers, and that can be clicked or tapped to make it easier for users to select and deselect options. Therefore, make sure to supply the label prop. If that’s not possible, make sure your standalone Label has an htmlFor prop that matches the id of the checkbox. Test that a checkbox and label are properly connected by clicking or tapping on the label and confirming that it activates the checkbox next to it.

If Checkbox is labeled by content elsewhere on the page, or a more complex label is needed, the labelDisplay prop can be used to visually hide the label. In this case, it is still available to screen reader users, but will not appear visually on the screen. See the Label visibility example for more detail.

Legends

All groups of related Checkboxes should have a legend, which is provided by wrapping them in Fieldset component.

import { useState } from 'react';
import { Box, Checkbox, Fieldset, Flex } from 'gestalt';

export default function Example() {
  const [checkedEn, setCheckedEn] = useState(false);
  const [checkedSp, setCheckedSp] = useState(false);
  const [checkedCh, setCheckedCh] = useState(false);

  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Fieldset legend="What languages would you like to learn?">
        <Flex direction="column" gap={{ column: 2, row: 0 }}>
          <Checkbox
            checked={checkedEn}
            id="english"
            label="English"
            name="english"
            onChange={({ checked }) => setCheckedEn(checked)}
          />
          <Checkbox
            checked={checkedSp}
            id="spanish"
            label="Spanish"
            name="spanish"
            onChange={({ checked }) => setCheckedSp(checked)}
          />
          <Checkbox
            checked={checkedCh}
            id="chinese"
            label="Chinese"
            name="chinese"
            onChange={({ checked }) => setCheckedCh(checked)}
          />
        </Flex>
      </Fieldset>
    </Box>
  );
}

Keyboard navigation

Checkbox has conventional keyboard support.

  • Users relying on the keyboard expect to move focus to each Checkbox by using the tab key or shift+tab when moving backwards
  • Setting disabled will prevent Checkbox from receiving keyboard focus or input

In order to ensure proper tab order, wrap a group of related Checkboxes in Fieldset.

Error message

Checkbox’s error state displays an error-themed color border. Checkbox must always show an error message to indicate error status to ensure color is not the only indicator of status or information. Use errorMessage prop to display the appropriate error message that helps the user resolve the problem. Error messages should be clear, direct and conversational. For an example, see Writing.

import { Checkbox, Flex } from 'gestalt';

export default function CheckboxExample() {
  return (
    <Flex
      alignItems="start"
      direction="column"
      gap={6}
      height="100%"
      justifyContent="center"
    >
      <Checkbox
        errorMessage="You must agree to the Terms and Conditions"
        id="error"
        label="I agree to the Terms and Conditions"
        name="error"
        onChange={() => {}}
      />
      <Checkbox
        checked
        errorMessage="You must read the privacy policy first!"
        id="error"
        label="I agree with the Privacy Policy"
        name="error"
        onChange={() => {}}
      />
    </Flex>
  );
}

Localization

Be sure to localize all text strings. Note that localization can lengthen text by 20 to 30 percent.

Variants

Size

Checkbox has size="sm" (16px) and size='md' (24px).

import { useState } from 'react';
import { Box, Checkbox, Flex } from 'gestalt';

export default function Example() {
  const [checked1, setChecked1] = useState(false);
  const [checked2, setChecked2] = useState(false);

  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Flex gap={{ column: 0, row: 6 }}>
        <Checkbox
          checked={checked1}
          id="sm"
          label="Small size"
          onChange={({ checked }) => setChecked1(checked)}
          size="sm"
        />
        <Checkbox
          checked={checked2}
          id="md"
          label="Medium size"
          onChange={({ checked }) => setChecked2(checked)}
        />
      </Flex>
    </Box>
  );
}

State

Checkbox has unchecked, checked, error, indeterminate and disabled states.

Indeterminate is a state that is neither checked nor unchecked — e.g. a "Select all" checkbox when not all items are selected or unselected. Indeterminism is purely presentational - the value of a checkbox and its indeterminism are independent.

Unchecked
import { Box, Checkbox, Flex } from 'gestalt';

const noop = () => {};

export default function Example() {
  return (
    <Box padding={4}>
      <Flex direction="column" gap={4} height="100%" width="100%">
        <Checkbox
          checked={false}
          helperText="Helper Text"
          id="Unchecked sm"
          label="Unchecked"
          onChange={noop}
          size="sm"
        />
        <Checkbox
          checked={false}
          helperText="Helper Text"
          id="Unchecked md"
          label="Unchecked"
          onChange={noop}
          size="md"
        />
      </Flex>
    </Box>
  );
}

Checked
import { Box, Checkbox, Flex } from 'gestalt';

const noop = () => {};

export default function Example() {
  return (
    <Box padding={4}>
      <Flex direction="column" gap={4} height="100%" width="100%">
        <Checkbox
          checked
          helperText="Helper Text"
          id="Checked sm"
          label="Checked"
          onChange={noop}
          size="sm"
        />

        <Checkbox
          checked
          helperText="Helper Text"
          id="Checked md"
          label="Checked"
          onChange={noop}
          size="md"
        />
      </Flex>
    </Box>
  );
}

Indeterminate
import { Box, Checkbox, Flex } from 'gestalt';

const noop = () => {};

export default function Example() {
  return (
    <Box padding={4}>
      <Flex direction="column" gap={4} height="100%" width="100%">
        <Checkbox
          checked
          helperText="Helper Text"
          id="Indeterminate sm"
          indeterminate
          label="Indeterminate"
          onChange={noop}
          size="sm"
        />
        <Checkbox
          checked
          helperText="Helper Text"
          id="Indeterminate md"
          indeterminate
          label="Indeterminate"
          onChange={noop}
          size="md"
        />
      </Flex>
    </Box>
  );
}

Disabled
import { Box, Checkbox, Flex } from 'gestalt';

const noop = () => {};

export default function Example() {
  return (
    <Box padding={4}>
      <Flex gap={8} height="100%" width="100%">
        <Flex direction="column" gap={6}>
          <Checkbox
            checked={false}
            disabled
            helperText="Helper Text"
            id="Disabled sm"
            label="Disabled"
            onChange={noop}
            size="sm"
          />
          <Checkbox
            checked
            disabled
            helperText="Helper Text"
            id="Disabled Checked sm"
            label="Disabled Checked"
            onChange={noop}
            size="sm"
          />
          <Checkbox
            disabled
            helperText="Helper Text"
            id="Disabled indeterminate sm"
            indeterminate
            label="Disabled indeterminate "
            onChange={noop}
            size="sm"
          />
        </Flex>
        <Flex direction="column" gap={6}>
          <Checkbox
            checked={false}
            disabled
            helperText="Helper Text"
            id="Disabled md"
            label="Disabled"
            onChange={noop}
            size="md"
          />
          <Checkbox
            checked
            disabled
            helperText="Helper Text"
            id="Disabled Checked md"
            label="Disabled Checked"
            onChange={noop}
            size="md"
          />
          <Checkbox
            disabled
            helperText="Helper Text"
            id="Disabled Indeterminate md"
            indeterminate
            label="Disabled indeterminate"
            onChange={noop}
            size="md"
          />
        </Flex>
      </Flex>
    </Box>
  );
}

Error
import { Box, Checkbox, Flex } from 'gestalt';

const noop = () => {};

export default function Example() {
  return (
    <Box padding={4}>
      <Flex gap={8} height="100%" width="100%">
        <Flex direction="column" gap={6}>
          <Checkbox
            checked={false}
            errorMessage="Error Message"
            helperText="Helper Text"
            id="Error sm"
            label="Error"
            onChange={noop}
            size="sm"
          />
          <Checkbox
            checked
            errorMessage="Error Message"
            helperText="Helper Text"
            id="Error Checked sm"
            label="Error Checked"
            onChange={noop}
            size="sm"
          />
          <Checkbox
            errorMessage="Error Message"
            helperText="Helper Text"
            id="Error Indeterminate sm"
            indeterminate
            label="Error indeterminate"
            onChange={noop}
            size="sm"
          />
        </Flex>
        <Flex direction="column" gap={6}>
          <Checkbox
            checked={false}
            errorMessage="Error Message"
            helperText="Helper Text"
            id="Error md"
            label="Error"
            onChange={noop}
            size="md"
          />
          <Checkbox
            checked
            errorMessage="Error Message"
            helperText="Helper Text"
            id="Error Checked md"
            label="Error Checked"
            onChange={noop}
            size="md"
          />
          <Checkbox
            errorMessage="Error Message"
            helperText="Helper Text"
            id="Error Indeterminate  md"
            indeterminate
            label="Error indeterminate"
            onChange={noop}
            size="md"
          />
        </Flex>
      </Flex>
    </Box>
  );
}

Helper text

Checkbox supports helperText

import { useState } from 'react';
import { Box, Checkbox, Fieldset, Flex } from 'gestalt';

export default function Example() {
  const [checkedEn, setCheckedEn] = useState(false);
  const [checkedSp, setCheckedSp] = useState(false);
  const [checkedCh, setCheckedCh] = useState(false);

  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Fieldset legend="What languages would you like to learn?">
        <Flex direction="column" gap={{ column: 2, row: 0 }}>
          <Checkbox
            checked={checkedEn}
            helperText="USA, India, and Pakistan have the top number of English speakers "
            id="english-info"
            label="English"
            name="languages"
            onChange={({ checked }) => {
              setCheckedEn(checked);
            }}
          />
          <Checkbox
            checked={checkedSp}
            helperText="Mexico, Colombia, and Spain are the top three Spanish-speaking countries"
            id="spanish-info"
            label="Spanish"
            name="languages"
            onChange={({ checked }) => {
              setCheckedSp(checked);
            }}
          />
          <Checkbox
            checked={checkedCh}
            helperText="Chinese has many varieties, including Cantonese and Mandarin"
            id="chinese-info"
            label="Chinese"
            name="languages"
            onChange={({ checked }) => {
              setCheckedCh(checked);
            }}
          />
        </Flex>
      </Fieldset>
    </Box>
  );
}

With Image

Checkbox supports images. When including images, you can use the helperText property to clearly describe the information being presented by the image, or use the image's alt text to provide more context.

Spacing is already accounted for; simply specify the width and height.

import { useState } from 'react';
import { Box, Checkbox, Fieldset, Flex, Image } from 'gestalt';

export default function CheckboxExample() {
  const [checkedCoral, setCheckedCoral] = useState(false);
  const [checkedBlue, setCheckedBlue] = useState(false);

  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Fieldset
        legend="Which backgrounds would you like to use?"
        legendDisplay="hidden"
      >
        <Flex direction="column" gap={{ column: 4, row: 0 }}>
          <Checkbox
            checked={checkedCoral}
            helperText="Botanical art in coral and green"
            id="coral"
            image={
              <Box height={100} width={80}>
                <Image
                  alt="Botanical art in coral and green"
                  fit="contain"
                  naturalHeight={1}
                  naturalWidth={1}
                  src="https://i.ibb.co/7bQQYkX/stock2.jpg"
                />
              </Box>
            }
            label="Coral"
            name="favorite art"
            onChange={({ checked }) => {
              setCheckedCoral(checked);
            }}
          />
          <Checkbox
            checked={checkedBlue}
            helperText="Typography and shoe in blue"
            id="blue"
            image={
              <Box height={100} width={80}>
                <Image
                  alt="Typography and shoe in blue"
                  fit="contain"
                  naturalHeight={1}
                  naturalWidth={1}
                  src="https://i.ibb.co/jVR29XV/stock5.jpg"
                />
              </Box>
            }
            label="Blue"
            name="favorite art"
            onChange={({ checked }) => {
              setCheckedBlue(checked);
            }}
          />
        </Flex>
      </Fieldset>
    </Box>
  );
}

Label visibility

In some cases, the label for a Checkbox is represented in a different way visually, as demonstrated below. In these instances, you can set labelDisplay="hidden" to ensure Checkbox is properly labeled for screen readers while using a different element to represent the label visually.

import { useState } from 'react';
import { Box, Checkbox, Table, Text } from 'gestalt';

export default function Example() {
  const [checked1, setChecked1] = useState(false);
  const [checked2, setChecked2] = useState(true);
  const [checked3, setChecked3] = useState(true);

  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Table accessibilityLabel="Campaign selection" maxHeight={200}>
        <Table.Header sticky>
          <Table.Row>
            <Table.HeaderCell>&nbsp;</Table.HeaderCell>
            <Table.HeaderCell>
              <Text weight="bold">Name</Text>
            </Table.HeaderCell>
          </Table.Row>
        </Table.Header>
        <Table.Body>
          <Table.Row>
            <Table.Cell>
              <Box width={20}>
                <Checkbox
                  checked={checked1}
                  id="label-visibility-example-checkbox-1"
                  label="Select Summertime picnic row"
                  labelDisplay="hidden"
                  onChange={({ checked }) => setChecked1(checked)}
                  size="sm"
                />
              </Box>
            </Table.Cell>
            <Table.Cell>
              <Text>Summertime picnic</Text>
            </Table.Cell>
          </Table.Row>
          <Table.Row>
            <Table.Cell>
              <Box width={20}>
                <Checkbox
                  checked={checked2}
                  id="label-visibility-example-checkbox-2"
                  label="Select Summer 1950 row"
                  labelDisplay="hidden"
                  onChange={({ checked }) => setChecked2(checked)}
                  size="sm"
                />
              </Box>
            </Table.Cell>
            <Table.Cell>
              <Text>Summer 1950</Text>
            </Table.Cell>
          </Table.Row>
          <Table.Row>
            <Table.Cell>
              <Box width={20}>
                <Checkbox
                  checked={checked3}
                  id="label-visibility-example-checkbox-3"
                  label="Select Back to school row"
                  labelDisplay="hidden"
                  onChange={({ checked }) => setChecked3(checked)}
                  size="sm"
                />
              </Box>
            </Table.Cell>
            <Table.Cell>
              <Text>Back to school</Text>
            </Table.Cell>
          </Table.Row>
        </Table.Body>
      </Table>
    </Box>
  );
}

Writing

Do
  • Be clear and brief with checkbox labels so they are easily scanned
Don't
  • Include lengthy text labels that make it hard for a user to scan a list of choices

Component quality checklist

Component quality checklist
Quality item
Status
Status description
Figma Library
Ready
Component is available in Figma for web and mobile web.
Responsive Web
Ready
Component responds to changing viewport sizes in web and mobile web.

RadioGroup
Use when presenting a user with a list of choices for which there can only be one selection.

Switch
Use for single-cell options that can be turned on or off. Examples include a list of settings that take effect immediately without having to confirm Form submission.

Fieldset
Use to group a list of related Checkboxes with a legend that describes the list.