Skip to Content

Checkbox

Checkboxes allow a user to select zero, one, or multiple values from a predefined list of 7 or less options.

Interaction Modes

Reviewing

Selecting

Install

yarn add @workday/canvas-kit-react

Component Type

Input

Platform

Web

Component

Sana Canvas

Delivery Channels

Web, Web Mobile

Version

16.1.7

Experience Surfaces

Page Body Inline

Component Type

Input

Platform

Web

Component

Sana Canvas

Delivery Channels

Web, Web Mobile

Version

16.1.7

Experience Surfaces

Page Body Inline

Anatomy

Image of a Checkbox Group in its default state.
  1. Form Field Label: The Form Field Label describes all of the checkboxes in the checkbox group and functions as a header.
  2. Checkbox: Checkboxes are aligned close to its label or by itself in some cases.
  3. Checkbox Label: Checkbox Labels give information about what to select or unselect.

Usage Guidance

  • The Form Field Label can be positioned in two places; above or left of the checkbox group for LTR languages. Form Field Labels are aligned to the right of the checkbox group for RTL languages.
  • Checkbox Labels are positioned to the right of Checkboxes for LTR languages or to the left of Checkboxes for RTL languages.
  • Checkboxes allow users to select one or many options. Selected options are shown as a white check with blue fill. Clicking it again will deselect the choice.
  • Each Checkbox is tied to a distinct value. Label for each selection should describe the choice and be kept as concise as possible.

When to Use

  • Use Checkboxes when the user is allowed to select 0, 1, or multiple values from a predefined list of 7 or less options.

When to Use Something Else

  • Consider using a Switch if the only options are yes or no.
  • For a list between 2 to 7 predefined options, consider using Radio Buttons or a Select to select one option.
  • Use a Prompt when the number of list items is large or unknown. Prompts have search capabilities and folders which provide users with the means to browse options. Prompts can be configured to support single or multi-select.

Examples

Basic Example

Checkbox may be used on its own without Form Field since it includes a <label> with a for attribute referencing the underlying <input type="checkbox"> element. For checkboxes grouped with FormFieldGroup, see FormField accessibility for hint, error, caution, and required state wiring.

import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';

export default () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  return <Checkbox checked={checked} label="I agree to the terms" onChange={handleChange} />;
};

Inverse

Checkbox with inverse variation

import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {Flex} from '@workday/canvas-kit-react/layout';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const styleOverrides = createStyles({
  backgroundColor: system.color.surface.contrast.default,
  padding: system.padding.md,
});

export default () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  return (
    <Flex cs={styleOverrides}>
      <Checkbox
        variant="inverse"
        checked={checked}
        label="I agree to the terms"
        onChange={handleChange}
      />
    </Flex>
  );
};

Disabled

Set the disabled prop of the Checkbox to prevent users from interacting with it.

import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';

export default () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  return (
    <Checkbox checked={checked} disabled label="I agree to the terms" onChange={handleChange} />
  );
};

Indeterminate

Set the indeterminate prop of the Checkbox to true to indicate the Checkbox is neither checked nor unchecked.

A common use case for an indeterminate Checkbox is when the value of a parent Checkbox is dependent on a number of child Checkboxes. The parent Checkbox is set to the indeterminate state if some (but not all) of its children are checked.

import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const listStyles = createStyles({
  listStyle: 'none',
  margin: 0,
  padding: 0,
});

const nestedListStyles = createStyles({
  listStyle: 'none',
  margin: 0,
  marginInlineStart: system.gap.xl,
  marginBlockStart: system.gap.sm,
  padding: 0,
  display: 'flex',
  flexDirection: 'column',
  gap: system.gap.sm,
});

export default () => {
  const [pizzaChecked, setPizzaChecked] = React.useState(false);
  const [pizzaIndeterminate, setPizzaIndeterminate] = React.useState(false);

  const [toppings, setToppings] = React.useState([
    {name: 'Pepperoni', checked: false},
    {name: 'Sausage', checked: false},
    {name: 'Bell Peppers', checked: false},
    {name: 'Olives', checked: false},
    {name: 'Onions', checked: false},
  ]);

  const handlePizzaChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const checked = event.target.checked;

    if (checked || (!checked && pizzaIndeterminate)) {
      setPizzaChecked(true);
      setToppings(
        toppings.map(topping => ({
          ...topping,
          checked: true,
        }))
      );
    } else {
      setPizzaChecked(false);
      setToppings(
        toppings.map(topping => ({
          ...topping,
          checked: false,
        }))
      );
    }

    setPizzaIndeterminate(false);
  };

  const handleToppingChange = (event: React.ChangeEvent<HTMLInputElement>, index: number) => {
    const newToppings = toppings.map(topping => ({...topping}));
    newToppings[index].checked = event.target.checked;
    setToppings(newToppings);

    const anyToppingChecked = newToppings.filter(topping => topping.checked).length > 0;
    const anyToppingUnchecked = newToppings.filter(topping => !topping.checked).length > 0;
    const allToppingChecked = !anyToppingUnchecked;
    setPizzaIndeterminate(anyToppingChecked && anyToppingUnchecked);
    setPizzaChecked(allToppingChecked);
  };

  return (
    <ul className={listStyles}>
      <li>
        <Checkbox
          checked={pizzaChecked}
          indeterminate={pizzaIndeterminate}
          label="Supreme Pizza Toppings"
          onChange={handlePizzaChange}
        />
        <ul className={nestedListStyles}>
          {toppings.map((topping, index) => (
            <li key={topping.name}>
              <Checkbox
                checked={topping.checked}
                label={topping.name}
                onChange={event => handleToppingChange(event, index)}
              />
            </li>
          ))}
        </ul>
      </li>
    </ul>
  );
};

Accessibility Note: Use semantic unordered list markup so that screen readers can communicate the nested hierarchy of the components to users.

Ref Forwarding

Checkbox supports ref forwarding . It will forward ref to its underlying <input type="checkbox"> element.

import React from 'react';

import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {changeFocus} from '@workday/canvas-kit-react/common';
import {Flex} from '@workday/canvas-kit-react/layout';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const containerStyles = createStyles({
  gap: system.gap.md,
  alignItems: 'flex-start',
  flexDirection: 'column',
});

export default () => {
  const [checked, setChecked] = React.useState(false);
  const ref = React.useRef<HTMLInputElement>(null);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  const handleClick = () => {
    changeFocus(ref.current);
  };

  return (
    <Flex cs={containerStyles}>
      <Checkbox checked={checked} label="I agree to the terms" onChange={handleChange} ref={ref} />
      <PrimaryButton onClick={handleClick}>Focus Checkbox</PrimaryButton>
    </Flex>
  );
};

Label Position Horizontal

Set the orientation prop of the wrapping FormFieldGroup to designate the position of the group label relative to the checkboxes. By default, the orientation will be set to vertical.

Confirm
import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';

export default () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  return (
    <FormFieldGroup orientation="horizontalStart">
      <FormFieldGroup.Label>Confirm</FormFieldGroup.Label>
      <FormFieldGroup.Field>
        <FormFieldGroup.Input
          as={Checkbox}
          checked={checked}
          label="I agree to the terms"
          onChange={handleChange}
        />
      </FormFieldGroup.Field>
    </FormFieldGroup>
  );
};

Required

Set the isRequired prop of a wrapping FormFieldGroup to true to indicate that the field is required. Labels for required fields are suffixed by a red asterisk.

A standalone checkbox does not need FormFieldGroup. This example wraps a single checkbox so isRequired can show the required asterisk on FormFieldGroup.Label. Use that wrapper only when the spec includes a required state (or a group name, hint, error, or caution). See Accessibility.

Confirm
import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';

export default () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  return (
    <FormFieldGroup isRequired={true}>
      <FormFieldGroup.Label>Confirm</FormFieldGroup.Label>
      <FormFieldGroup.Field>
        <FormFieldGroup.Input
          as={Checkbox}
          checked={checked}
          label="I agree to the terms"
          onChange={handleChange}
        />
      </FormFieldGroup.Field>
    </FormFieldGroup>
  );
};

Error States

Set the error prop of the wrapping FormFieldGroup to "caution" or "error" to set the Checkbox to the Alert or Error state, respectively. Render FormFieldGroup.Hint with the message text so assistive technology can associate the hint with the group. Keep the Checkbox label so each control retains its own accessible name; FormFieldGroup.Label only provides the group name.

The error prop may be applied directly to the Checkbox with a value of "caution" or "error" if FormFieldGroup is not being used.

Caution

Confirm

You must agree to the terms before proceeding

import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';

export default () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  return (
    <FormFieldGroup error="caution">
      <FormFieldGroup.Label>Confirm</FormFieldGroup.Label>
      <FormFieldGroup.Field>
        <FormFieldGroup.Input
          as={Checkbox}
          checked={checked}
          error={Checkbox.ErrorType.Caution}
          label="I agree to the terms"
          onChange={handleChange}
        />
        <FormFieldGroup.Hint>You must agree to the terms before proceeding</FormFieldGroup.Hint>
      </FormFieldGroup.Field>
    </FormFieldGroup>
  );
};

Error

Confirm

You must agree to the terms before proceeding

import React from 'react';

import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';

export default () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  return (
    <FormFieldGroup error="error">
      <FormFieldGroup.Label>Confirm</FormFieldGroup.Label>
      <FormFieldGroup.Field>
        <FormFieldGroup.Input
          as={Checkbox}
          checked={checked}
          error={Checkbox.ErrorType.Error}
          label="I agree to the terms"
          onChange={handleChange}
        />
        <FormFieldGroup.Hint>You must agree to the terms before proceeding</FormFieldGroup.Hint>
      </FormFieldGroup.Field>
    </FormFieldGroup>
  );
};

Custom Styles

Checkbox supports custom styling via the cs prop. For more information, check our “How To Customize Styles” .

Accessibility

The primary accessibility goal is a visible, programmatically determinable name and a checked, unchecked, or mixed state that assistive technology can expose. Use Checkbox when the user can select zero, one, or many independent options. For mutually exclusive choices, use Radio instead. When checkboxes answer the same question, or need hint, error, caution, or required association, see FormField’s accessibility documentation.

Minimum Accessible Structure

The following matches the Basic Example: a Checkbox with a non-empty label. FormFieldGroup is not required for a single standalone checkbox with no hint, error, caution, or required state.

import {Checkbox} from '@workday/canvas-kit-react/checkbox'; <Checkbox label="I agree to the terms" />;

Built-in Behaviors

Canvas Kit applies these automatically on Checkbox. When checkboxes that answer the same question are composed with FormFieldGroup subcomponents, that grouping wiring is also applied automatically. Do not duplicate them in consuming code.

ARIA and DOM (applied by Checkbox):

  • Checkbox: Renders a native <input type="checkbox">. Canvas Kit assigns an id with useUniqueId unless you pass id.
  • label: Renders a visible <label htmlFor={id}> so the control has an accessible name and clicking the text activates the input.
  • indeterminate: Sets aria-checked="mixed" and the input’s native indeterminate property. Otherwise aria-checked follows the checked prop.
  • disabled: Maps to the native disabled attribute.
  • ref: Forwards to the underlying <input type="checkbox">.

Keyboard (native checkbox behavior):

Checkbox uses native <input type="checkbox"> keyboard behavior (tab order, Space to toggle, and label activation). Do not intercept Space or otherwise prevent the native toggle.

Screen reader expectations (when built-in behaviors are used as intended):

  • On focus, assistive technology announces the Checkbox label and checked, unchecked, or mixed state
  • Disabled checkboxes are announced as unavailable

For group, hint, error, and required association, see FormField’s Built-in Behaviors.

Accessibility Requirements

Required in application code for an accessible Checkbox. Rows marked (conditional) apply only when the situation matches—otherwise omit.

If no design spec is provided: use a visible, non-empty Checkbox label. Omit FormFieldGroup unless the spec includes a group name, more than one independent option for the same question, or hint, error, caution, or required state. Omit FormFieldGroup.Hint, isRequired, error, indeterminate, disabled, a custom id, and a ref unless the spec requires them.

Choose a composition:

  • Standalone Checkbox with label — one control with no hint, error, caution, or required state
  • FormFieldGroup — one question with two or more independent options, or any checkbox that needs a group name, hint, error, caution, or required state
  • Nested <ul> / <li> — parent checkbox with nested children and indeterminate. Do not use FormFieldGroup for that hierarchy. Checkboxes that answer different questions stay in separate compositions.

Programmatic focus (conditional — omit by default):

Attach a ref only when the product must move focus to the checkbox after an action (for example, Submit in Ref Forwarding). Do not attach a ref or call focus() unless the design or developer asks for it.

RequirementHow to satisfy
Accessible nameNon-empty label on every Checkbox. FormFieldGroup.Label names the group only (div with an id); it is not a <label> and does not replace label.
Group wiring (conditional)When the spec is one question with two or more independent options, or includes a group name, hint, error, caution, or required state: FormFieldGroup + FormFieldGroup.Label + FormFieldGroup.Input as={Checkbox}. Put hint, error, caution, and required on the group — see FormField accessibility. See Required and Error States.
Visual error or caution (conditional)When FormFieldGroup has error="error" or error="caution", also set error on Checkbox to the same state so the visual ring appears. See Caution and Error.
Indeterminate parent (conditional)When a parent checkbox’s value depends on nested children and some (but not all) children are checked: set indeterminate on the parent Checkbox; keep a non-empty label on the parent and on each child; nest the children in a <ul> inside the parent’s <li>. See Indeterminate.
Disabled (conditional)disabled on Checkbox when the spec marks the option unavailable. See Disabled.
Programmatic focus (conditional)ref on Checkbox (or FormFieldGroup.Input) and move focus when the product requires it — omit by default (see Programmatic focus above and Ref Forwarding).

Summary for code generation:

  • REQUIRED: non-empty label
  • CONDITIONAL: FormFieldGroup for one question with two or more independent options, or for hint, error, caution, or required; error on Checkbox when the group is in caution or error; nested list + indeterminate for a parent/child tree; disabled; programmatic focus via ref. See FormField accessibility for group hint, error, caution, and required.

Anti-Patterns

Do not generate code that does the following (see Accessibility Requirements above for what to supply instead):

  • Manually set aria-checked or htmlFor on Checkbox, or pass an id when the spec does not require a known id — Canvas Kit wires aria-checked and htmlFor, and assigns an id with useUniqueId unless you pass one (see If no design spec is provided)
  • Ignore Choose a composition — do not wrap a standalone checkbox with no group name, hint, error, caution, or required state in FormFieldGroup; do not put different questions in one group; do not use FormFieldGroup for a parent/child indeterminate tree
  • Wrap Checkbox with FormField.Input — Checkbox already renders its own <label>. When a group is required, use FormFieldGroup.Input as={Checkbox} (see Group wiring)
  • Omit label because FormFieldGroup.Label is present — the group label does not name the individual control
  • Set aria-checked="mixed" without indeterminate
  • Use aria-disabled instead of disabled — Checkbox maps unavailability to the native disabled prop
  • Use disabled when the spec says users must still focus the control to hear why it is unavailable. Only in that case keep the checkbox enabled and put the explanation in FormFieldGroup.Hint or on an adjacent focusable control
  • Use Checkbox for mutually exclusive choices — use Radio instead

Component API

Checkbox

Props

Props extend from input. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
checkedboolean

If true, set the Checkbox to the checked state.

false
disabledboolean

If true, set the Checkbox to the disabled state.

false
error

The type of error associated with the Checkbox (if applicable).

idstring

The HTML id of the underlying checkbox input element. This is required if label is defined as a non-empty string.

indeterminateboolean

If true, set the Checkbox to an indeterminate state. Use this on a Checkbox with nested child Checkboxes to denote that some (but not all) child Checkboxes are checked.

false
labelstring

The text of the Checkbox label.

''
onChange(e: <>) => void

The function called when the Checkbox state changes.

valuestring

The value of the Checkbox.

variant 'inverse' | undefined

The variant for the checkbox

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
childrenReact.ReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

input
refReact.Ref<R = input>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Checkbox.ErrorType

Basic type information:

ErrorType

Content Guidelines

  • Form Field Labels are written in title case.
  • The Checkbox Label for each individual selection are kept as concise as possible and written in sentence case.