Checkbox Group
Checkbox Groups combine a series of checkboxes together.
'use client';
import * as React from 'react';
import * as Checkbox from '@base_ui/react/Checkbox';
import * as CheckboxGroup from '@base_ui/react/CheckboxGroup';
import * as Field from '@base_ui/react/Field';
import Check from '@mui/icons-material/Check';
export default function UnstyledCheckboxIndeterminateGroup() {
  return (
    <Field.Root>
      <div style={{ display: 'flex', flexDirection: 'column' }}>
        <CheckboxGroup.Root defaultValue={['red']}>
          <Field.Label className="CheckboxGroup-label">Colors</Field.Label>
          <div style={{ display: 'flex', flexDirection: 'column' }}>
            <Field.Root>
              <Checkbox.Root className="Checkbox" name="red">
                <Checkbox.Indicator className="Checkbox-indicator">
                  <Check className="Check" />
                </Checkbox.Indicator>
              </Checkbox.Root>
              <Field.Label className="Checkbox-label">Red</Field.Label>
            </Field.Root>
            <Field.Root>
              <Checkbox.Root className="Checkbox" name="green">
                <Checkbox.Indicator className="Checkbox-indicator">
                  <Check className="Check" />
                </Checkbox.Indicator>
              </Checkbox.Root>
              <Field.Label className="Checkbox-label">Green</Field.Label>
            </Field.Root>
            <Field.Root>
              <Checkbox.Root className="Checkbox" name="blue">
                <Checkbox.Indicator className="Checkbox-indicator">
                  <Check className="Check" />
                </Checkbox.Indicator>
              </Checkbox.Root>
              <Field.Label className="Checkbox-label">Blue</Field.Label>
            </Field.Root>
          </div>
        </CheckboxGroup.Root>
        <Styles />
      </div>
    </Field.Root>
  );
}
const grey = {
  100: '#E5EAF2',
  300: '#C7D0DD',
  500: '#9DA8B7',
  600: '#6B7A90',
  800: '#303740',
  900: '#1C2025',
};
function Styles() {
  return (
    <style>
      {`
      .Check {
        height: 100%;
        width: 100%;
      }
      .CheckboxGroup-label {
        display: flex;
        font-weight: bold;
        gap: 8px;
        margin-bottom: 8px;
        font-size: 17px;
      }
      .Checkbox-label {
        display: flex;
        font-weight: 500;
        gap: 8px;
        margin-bottom: 8px;
      }
      .Checkbox {
        all: unset;
        box-sizing: border-box;
        text-align: center;
        width: 24px;
        height: 24px;
        padding: 0;
        border-radius: 4px;
        border: 2px solid ${grey[600]};
        background: none;
        transition-property: background, border-color;
        transition-duration: 0.15s;
      }
      .Checkbox[data-disabled] {
        opacity: 0.4;
        cursor: not-allowed;
      }
      .Checkbox:focus-visible {
        outline: 2px solid ${grey[500]};
        outline-offset: 2px;
      }
      .Checkbox[data-state="checked"] {
        border-color: ${grey[800]};
        background: ${grey[800]};
      }
      .Checkbox-indicator {
        height: 100%;
        display: inline-block;
        visibility: hidden;
        color: ${grey[100]};
      }
      .Checkbox-indicator[data-state="checked"] {
        visibility: visible;
      }
      .Checkbox-icon {
        width: 100%;
        height: 100%;
      }
      @media (prefers-color-scheme: dark) {
        .Checkbox {
          border-color: ${grey[500]};
        }
        .Checkbox:focus-visible {
          outline: 2px solid ${grey[600]};
          outline-offset: 2px;
        }
        .Checkbox[data-state="checked"] {
          border-color: ${grey[300]};
          background: ${grey[300]};
        }
        .Checkbox:hover:not([data-disabled]) {
          border-color: ${grey[100]};
        }
        .Checkbox-indicator {
          color: ${grey[900]};
        }
      }
    `}
    </style>
  );
}
Installation
Base UI components are all available as a single package.
npm install @base_ui/react
Once you have the package installed, import the component.
import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; import * as Checkbox from '@base_ui/react/Checkbox';
Anatomy
Checkbox Group is composed of a Root component and Checkbox components:
- <CheckboxGroup.Root />renders a- <div>with a- grouprole.
- <Checkbox.Root />renders an individual- <button>checkbox.
<CheckboxGroup.Root>
  <Checkbox.Root />
  <Checkbox.Root />
</CheckboxGroup.Root>Labeling
Field components are used to label the Checkbox Group and individual Checkboxes:
import * as Field from '@base_ui/react/Field';<Field.Root>
  <CheckboxGroup.Root>
    <Field.Label>Colors</Field.Label>
    <Field.Root>
      <Checkbox.Root name="red" />
      <Field.Label>Red</Field.Label>
    </Field.Root>
    <Field.Root>
      <Checkbox.Root name="blue" />
      <Field.Label>Blue</Field.Label>
    </Field.Root>
  </CheckboxGroup.Root>
</Field.Root>Controlled
The value and onValueChange props control the Checkbox Group with external state. value is an array of strings matching the name props of Checkboxes that are currently checked:
const [value, setValue] = useState(['red']);
 
return (
  <CheckboxGroup.Root value={value} onValueChange={setValue}>
    <Checkbox.Root name="red" /> {/* Checked */}
    <Checkbox.Root name="green" />
    <Checkbox.Root name="blue" />
  </CheckboxGroup.Root>
);Parent Checkbox
A Checkbox can control a group of child Checkboxes.
- Make CheckboxGroup.Rootcontrolled and addallValuesas a prop — an array of strings that contains the names of all the child checkboxes.
- Add a parentprop to theCheckbox.Rootcomponent that controls the other (child) Checkboxes inside the group.
- Give the child Checkboxes a nameprop that identifies them inside theallValuesarray.
const allValues = ['a', 'b', 'c'];
 
function App() {
  const [value, setValue] = useState([]);
  return (
    <CheckboxGroup.Root value={value} onValueChange={setValue} allValues={allValues}>
      <Checkbox.Root parent />
      {allValues.map((value) => (
        <Checkbox.Root key={value} name={value} />
      ))}
    </CheckboxGroup.Root>
  );
}'use client';
import * as React from 'react';
import * as BaseCheckbox from '@base_ui/react/Checkbox';
import * as CheckboxGroup from '@base_ui/react/CheckboxGroup';
import * as Field from '@base_ui/react/Field';
import { styled } from '@mui/system';
import HorizontalRule from '@mui/icons-material/HorizontalRule';
import Check from '@mui/icons-material/Check';
const colors = ['red', 'green', 'blue'];
export default function UnstyledCheckboxGroupNested() {
  const [value, setValue] = React.useState<string[]>([]);
  return (
    <Field.Root style={{ display: 'flex', flexDirection: 'column' }}>
      <CheckboxGroup.Root
        allValues={colors}
        value={value}
        onValueChange={setValue}
        preserveChildStates={false}
      >
        <CheckboxGroupLabel>Colors</CheckboxGroupLabel>
        <FieldRoot render={<ul />}>
          <Checkbox parent>
            <Indicator
              render={(props, { indeterminate }) => (
                <span {...props}>
                  {indeterminate ? <HorizontalRuleIcon /> : <CheckIcon />}
                </span>
              )}
            />
          </Checkbox>
          <CheckboxLabel>All Colors</CheckboxLabel>
        </FieldRoot>
        <List>
          {colors.map((color) => (
            <FieldListItem key={color} render={<li />}>
              <Checkbox name={color}>
                <Indicator>
                  <CheckIcon />
                </Indicator>
              </Checkbox>
              <CheckboxLabel>{color}</CheckboxLabel>
            </FieldListItem>
          ))}
        </List>
      </CheckboxGroup.Root>
    </Field.Root>
  );
}
const blue = {
  400: '#3399FF',
  600: '#0072E6',
  800: '#004C99',
};
const grey = {
  100: '#E5EAF2',
  400: '#B0B8C4',
  800: '#303740',
};
const CheckboxGroupLabel = styled(Field.Label)`
  display: block;
  font-weight: bold;
  font-size: 18px;
  margin-bottom: 8px;
`;
const Checkbox = styled(BaseCheckbox.Root)(
  ({ theme }) => `
    width: 24px;
    height: 24px;
    padding: 0;
    border-radius: 4px;
    border: 2px solid ${blue[600]};
    background: none;
    transition-property: background, border-color;
    transition-duration: 0.15s;
    outline: none;
    &[data-disabled] {
      opacity: 0.4;
      cursor: not-allowed;
    }
    &:focus-visible {
      outline: 2px solid ${theme.palette.mode === 'dark' ? blue[800] : blue[400]};
      outline-offset: 2px;
    }
    &[data-state="checked"], &[data-state="mixed"] {
      border-color: transparent;
      background: ${blue[600]};
    }
  `,
);
const HorizontalRuleIcon = styled(HorizontalRule)`
  height: 100%;
  width: 100%;
`;
const CheckIcon = styled(Check)`
  height: 100%;
  width: 100%;
`;
const Indicator = styled(BaseCheckbox.Indicator)`
  height: 100%;
  display: inline-block;
  visibility: hidden;
  color: ${grey[100]};
  &[data-state='checked'],
  &[data-state='mixed'] {
    visibility: visible;
  }
`;
const FieldRoot = styled(Field.Root)`
  display: flex;
  align-items: center;
  margin-bottom: 8px;
  padding: 0;
`;
const List = styled('ul')`
  list-style: none;
  padding: 0;
  margin: 0;
  margin-left: 32px;
`;
const FieldListItem = styled(Field.Root)`
  display: flex;
  align-items: center;
  &:not(:last-child) {
    margin-bottom: 8px;
  }
`;
const CheckboxLabel = styled(Field.Label)`
  display: flex;
  gap: 8px;
  text-transform: capitalize;
  padding-left: 8px;
`;
To preserve the initial state of the child checkboxes when the parent checkbox is toggled, set the preserveChildStates prop to true:
<CheckboxGroup.Root preserveChildStates>
  <Checkbox.Root parent />
  {allValues.map((value) => (
    <Checkbox.Root key={value} name={value} />
  ))}
</CheckboxGroup.Root>API Reference
CheckboxGroupRoot
The foundation for building custom-styled checkbox groups.
| Prop | Type | Default | Description | 
|---|---|---|---|
| allValues | arrayOf | All values of the checkboxes in the group. | |
| className | union | Class names applied to the element or a function that returns them based on the component's state. | |
| defaultValue | arrayOf | The default checked values of the checkbox group. Use when uncontrolled. | |
| disabled | bool | false | Whether the checkbox group is disabled. | 
| onValueChange | func | A callback function that is called when the value of the checkbox group changes. Use when controlled. | |
| preserveChildStates | bool | false | Whether the parent checkbox should preserve its child states when checked/unchecked, leading to a tri-state checkbox group. | 
| render | union | A function to customize rendering of the component. | |
| value | arrayOf | The currently checked values of the checkbox group. Use when controlled. |