useCheckboxGroup

Provides the behavior and accessibility implementation for a checkbox group component. Checkbox groups allow users to select multiple items from a list of options.

installyarn add react-aria
version3.29.0
usageimport {useCheckboxGroup, useCheckboxGroupItem} from 'react-aria'

API#


useCheckboxGroup( (props: AriaCheckboxGroupProps, , state: CheckboxGroupState )): CheckboxGroupAria useCheckboxGroupItem( props: AriaCheckboxGroupItemProps, state: CheckboxGroupState, inputRef: RefObject<HTMLInputElement> ): CheckboxAria

Features#


Checkbox groups can be built in HTML with the <fieldset> and <input> elements, however these can be difficult to style. useCheckboxGroup and useCheckboxGroupItem help achieve accessible checkbox groups that can be styled as needed.

  • Checkbox groups are exposed to assistive technology via ARIA
  • Each checkbox is built with a native HTML <input> element, which can be optionally visually hidden to allow custom styling
  • Full support for browser features like form autofill
  • Keyboard focus management and cross browser normalization
  • Group and checkbox labeling support for assistive technology

Anatomy#


ShoppingMusicTravelInputInterestsCheckbox group labelGroupCheckbox label

A checkbox group consists of a set of checkboxes, and a label. Each checkbox includes a label and a visual selection indicator. Zero or more checkboxes within the group can be selected at a time. Users may click or touch a checkbox to select it, or use the Tab key to navigate to it and the Space key to toggle it.

useCheckboxGroup returns props for the group and its label, which you should spread onto the appropriate element:

NameTypeDescription
groupPropsDOMAttributesProps for the checkbox group wrapper element.
labelPropsDOMAttributesProps for the checkbox group's visible label (if any).
descriptionPropsDOMAttributesProps for the checkbox group description element, if any.
errorMessagePropsDOMAttributesProps for the checkbox group error message element, if any.

useCheckboxGroupItem returns props for an individual checkbox:

NameTypeDescription
inputPropsInputHTMLAttributes<HTMLInputElement>Props for the input element.
isSelectedbooleanWhether the checkbox is selected.
isPressedbooleanWhether the checkbox is in a pressed state.
isDisabledbooleanWhether the checkbox is disabled.
isReadOnlybooleanWhether the checkbox is read only.
isInvalidbooleanWhether the checkbox is invalid.

Selection state is managed by the useCheckboxGroupState hook in @react-stately/checkbox. The state object should be passed as an option to useCheckboxGroup and useCheckboxGroupItem.

Individual checkboxes must have a visual label. If the checkbox group does not have a visible label, an aria-label or aria-labelledby prop must be passed instead to identify the element to assistive technology.

Note: useCheckboxGroupItem should only be used when it is contained within a checkbox group. For a standalone checkbox, use the useCheckbox hook instead.

Example#


This example uses native input elements for the checkboxes, and React context to share state from the group to each checkbox. An HTML <label> element wraps the native input and the text to provide an implicit label for the checkbox.

import {useCheckboxGroupState} from 'react-stately';
import {useCheckboxGroup, useCheckboxGroupItem} from 'react-aria';

let CheckboxGroupContext = React.createContext(null);

function CheckboxGroup(props) {
  let { children, label, description, errorMessage } = props;
  let state = useCheckboxGroupState(props);
  let { groupProps, labelProps, descriptionProps, errorMessageProps } =
    useCheckboxGroup(props, state);

  return (
    <div {...groupProps}>
      <span {...labelProps}>{label}</span>
      <CheckboxGroupContext.Provider value={state}>
        {children}
      </CheckboxGroupContext.Provider>
      {description && (
        <div {...descriptionProps} style={{ fontSize: 12 }}>{description}</div>
      )}
      {errorMessage && state.isInvalid &&
        (
          <div {...errorMessageProps} style={{ color: 'red', fontSize: 12 }}>
            {errorMessage}
          </div>
        )}
    </div>
  );
}

function Checkbox(props) {
  let { children } = props;
  let state = React.useContext(CheckboxGroupContext);
  let ref = React.useRef(null);
  let { inputProps } = useCheckboxGroupItem(props, state, ref);

  let isDisabled = state.isDisabled || props.isDisabled;
  let isSelected = state.isSelected(props.value);

  return (
    <label
      style={{
        display: 'block',
        color: (isDisabled && 'var(--gray)') || (isSelected && 'var(--blue)')
      }}
    >
      <input {...inputProps} ref={ref} />
      {children}
    </label>
  );
}

<CheckboxGroup label="Favorite sports">
  <Checkbox value="soccer" isDisabled>Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
import {useCheckboxGroupState} from 'react-stately';
import {
  useCheckboxGroup,
  useCheckboxGroupItem
} from 'react-aria';

let CheckboxGroupContext = React.createContext(null);

function CheckboxGroup(props) {
  let { children, label, description, errorMessage } =
    props;
  let state = useCheckboxGroupState(props);
  let {
    groupProps,
    labelProps,
    descriptionProps,
    errorMessageProps
  } = useCheckboxGroup(props, state);

  return (
    <div {...groupProps}>
      <span {...labelProps}>{label}</span>
      <CheckboxGroupContext.Provider value={state}>
        {children}
      </CheckboxGroupContext.Provider>
      {description && (
        <div {...descriptionProps} style={{ fontSize: 12 }}>
          {description}
        </div>
      )}
      {errorMessage && state.isInvalid &&
        (
          <div
            {...errorMessageProps}
            style={{ color: 'red', fontSize: 12 }}
          >
            {errorMessage}
          </div>
        )}
    </div>
  );
}

function Checkbox(props) {
  let { children } = props;
  let state = React.useContext(CheckboxGroupContext);
  let ref = React.useRef(null);
  let { inputProps } = useCheckboxGroupItem(
    props,
    state,
    ref
  );

  let isDisabled = state.isDisabled || props.isDisabled;
  let isSelected = state.isSelected(props.value);

  return (
    <label
      style={{
        display: 'block',
        color: (isDisabled && 'var(--gray)') ||
          (isSelected && 'var(--blue)')
      }}
    >
      <input {...inputProps} ref={ref} />
      {children}
    </label>
  );
}

<CheckboxGroup label="Favorite sports">
  <Checkbox value="soccer" isDisabled>Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
import {useCheckboxGroupState} from 'react-stately';
import {
  useCheckboxGroup,
  useCheckboxGroupItem
} from 'react-aria';

let CheckboxGroupContext =
  React.createContext(
    null
  );

function CheckboxGroup(
  props
) {
  let {
    children,
    label,
    description,
    errorMessage
  } = props;
  let state =
    useCheckboxGroupState(
      props
    );
  let {
    groupProps,
    labelProps,
    descriptionProps,
    errorMessageProps
  } = useCheckboxGroup(
    props,
    state
  );

  return (
    <div {...groupProps}>
      <span
        {...labelProps}
      >
        {label}
      </span>
      <CheckboxGroupContext.Provider
        value={state}
      >
        {children}
      </CheckboxGroupContext.Provider>
      {description && (
        <div
          {...descriptionProps}
          style={{
            fontSize: 12
          }}
        >
          {description}
        </div>
      )}
      {errorMessage &&
        state
          .isInvalid &&
        (
          <div
            {...errorMessageProps}
            style={{
              color:
                'red',
              fontSize:
                12
            }}
          >
            {errorMessage}
          </div>
        )}
    </div>
  );
}

function Checkbox(
  props
) {
  let { children } =
    props;
  let state = React
    .useContext(
      CheckboxGroupContext
    );
  let ref = React.useRef(
    null
  );
  let { inputProps } =
    useCheckboxGroupItem(
      props,
      state,
      ref
    );

  let isDisabled =
    state.isDisabled ||
    props.isDisabled;
  let isSelected = state
    .isSelected(
      props.value
    );

  return (
    <label
      style={{
        display: 'block',
        color:
          (isDisabled &&
            'var(--gray)') ||
          (isSelected &&
            'var(--blue)')
      }}
    >
      <input
        {...inputProps}
        ref={ref}
      />
      {children}
    </label>
  );
}

<CheckboxGroup label="Favorite sports">
  <Checkbox
    value="soccer"
    isDisabled
  >
    Soccer
  </Checkbox>
  <Checkbox value="baseball">
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>

Styling#


See the useCheckbox docs for details on how to customize the styling of checkbox elements.

Styled examples#


Button Group
A multi-selectable segmented ButtonGroup component.

Usage#


The following examples show how to use the CheckboxGroup component created in the above example.

Default value#

An initial, uncontrolled value can be provided to the CheckboxGroup using the defaultValue prop, which accepts an array of selected items that map to the value prop on each Checkbox.

<CheckboxGroup
  label="Favorite sports (uncontrolled)"
  defaultValue={['soccer', 'baseball']}
>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports (uncontrolled)"
  defaultValue={['soccer', 'baseball']}
>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports (uncontrolled)"
  defaultValue={[
    'soccer',
    'baseball'
  ]}
>
  <Checkbox value="soccer">
    Soccer
  </Checkbox>
  <Checkbox value="baseball">
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>

Controlled value#

A controlled value can be provided using the value prop, which accepts an array of selected items, which map to the value prop on each Checkbox. The onChange event is fired when the user checks or unchecks an option. It receives a new array containing the updated selected values.

function Example() {
  let [selected, setSelected] = React.useState(['soccer', 'baseball']);

  return (
    <CheckboxGroup
      label="Favorite sports (controlled)"
      value={selected}
      onChange={setSelected}
    >
      <Checkbox value="soccer">Soccer</Checkbox>
      <Checkbox value="baseball">Baseball</Checkbox>
      <Checkbox value="basketball">Basketball</Checkbox>
    </CheckboxGroup>
  );
}
function Example() {
  let [selected, setSelected] = React.useState([
    'soccer',
    'baseball'
  ]);

  return (
    <CheckboxGroup
      label="Favorite sports (controlled)"
      value={selected}
      onChange={setSelected}
    >
      <Checkbox value="soccer">Soccer</Checkbox>
      <Checkbox value="baseball">Baseball</Checkbox>
      <Checkbox value="basketball">Basketball</Checkbox>
    </CheckboxGroup>
  );
}
function Example() {
  let [
    selected,
    setSelected
  ] = React.useState([
    'soccer',
    'baseball'
  ]);

  return (
    <CheckboxGroup
      label="Favorite sports (controlled)"
      value={selected}
      onChange={setSelected}
    >
      <Checkbox value="soccer">
        Soccer
      </Checkbox>
      <Checkbox value="baseball">
        Baseball
      </Checkbox>
      <Checkbox value="basketball">
        Basketball
      </Checkbox>
    </CheckboxGroup>
  );
}

Description#

The description prop can be used to associate additional help text with a checkbox group.

<CheckboxGroup
  label="Favorite sports"
  description="Select your favorite sports."
>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  description="Select your favorite sports."
>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  description="Select your favorite sports."
>
  <Checkbox value="soccer">
    Soccer
  </Checkbox>
  <Checkbox value="baseball">
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>

Error message#

The errorMessage prop can be used to help the user fix a validation error. It should be combined with the isInvalid prop to semantically mark the checkbox group as invalid for assistive technologies.

<CheckboxGroup
  label="Favorite sports"
  errorMessage="Invalid selection of sports."
  isInvalid
>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  errorMessage="Invalid selection of sports."
  isInvalid
>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  errorMessage="Invalid selection of sports."
  isInvalid
>
  <Checkbox value="soccer">
    Soccer
  </Checkbox>
  <Checkbox value="baseball">
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>

Disabled#

The entire CheckboxGroup can be disabled with the isDisabled prop.

<CheckboxGroup label="Favorite sports" isDisabled>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup label="Favorite sports" isDisabled>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  isDisabled
>
  <Checkbox value="soccer">
    Soccer
  </Checkbox>
  <Checkbox value="baseball">
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>

To disable an individual checkbox, pass isDisabled to the Checkbox instead.

<CheckboxGroup label="Favorite sports">
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball" isDisabled>Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup label="Favorite sports">
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball" isDisabled>Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup label="Favorite sports">
  <Checkbox value="soccer">
    Soccer
  </Checkbox>
  <Checkbox
    value="baseball"
    isDisabled
  >
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>

Read only#

The isReadOnly prop makes the selection immutable. Unlike isDisabled, the CheckboxGroup remains focusable. See the MDN docs for more information.

<CheckboxGroup label="Favorite sports" defaultValue={['baseball']} isReadOnly>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  defaultValue={['baseball']}
  isReadOnly
>
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  defaultValue={[
    'baseball'
  ]}
  isReadOnly
>
  <Checkbox value="soccer">
    Soccer
  </Checkbox>
  <Checkbox value="baseball">
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>

HTML forms#

CheckboxGroup supports the name prop, paired with the Checkbox value prop, for integration with HTML forms.

<CheckboxGroup label="Favorite sports" name="sports">
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup label="Favorite sports" name="sports">
  <Checkbox value="soccer">Soccer</Checkbox>
  <Checkbox value="baseball">Baseball</Checkbox>
  <Checkbox value="basketball">Basketball</Checkbox>
</CheckboxGroup>
<CheckboxGroup
  label="Favorite sports"
  name="sports"
>
  <Checkbox value="soccer">
    Soccer
  </Checkbox>
  <Checkbox value="baseball">
    Baseball
  </Checkbox>
  <Checkbox value="basketball">
    Basketball
  </Checkbox>
</CheckboxGroup>