moduix

Checkbox Group

A composable group for managing shared state across multiple checkboxes.

API Reference

Original primitive API

Behavior, accessibility details, and low-level props are documented by Base UI.

Base UI API

Basic

Notification Channels
import {  CheckboxGroup,  CheckboxGroupItem,  CheckboxGroupItemControl,  CheckboxGroupItemLabel,  CheckboxGroupLabel,  CheckboxGroupList,} from "moduix";import { useId } from "react";export function CheckboxGroupDemo() {  const labelId = useId();  return (    <CheckboxGroup aria-labelledby={labelId} defaultValue={["email"]}>      <CheckboxGroupLabel id={labelId}>Notification Channels</CheckboxGroupLabel>      <CheckboxGroupList>        {options.map((option) => (          <CheckboxGroupItem key={option.value}>            <CheckboxGroupItemControl value={option.value} name="notifications" />            <CheckboxGroupItemLabel>{option.label}</CheckboxGroupItemLabel>          </CheckboxGroupItem>        ))}      </CheckboxGroupList>    </CheckboxGroup>  );}
const options = [  { value: "email", label: "Email updates" },  { value: "push", label: "Push notifications" },  { value: "sms", label: "SMS alerts" },];

Full list of component variables available for project-level overrides.

PropertyDefaultDescription
--checkbox-bgvar(--color-background)Controls unchecked checkbox background.
--checkbox-bg-checkedvar(--color-primary)Controls checked checkbox background.
--checkbox-bg-hovervar(--color-accent)Controls unchecked hover background.
--checkbox-border-colorvar(--color-border)Controls unchecked checkbox border color.
--checkbox-border-color-checkedvar(--color-primary)Controls checked and indeterminate border color.
--checkbox-border-widthvar(--border-width-sm)Controls checkbox border width.
--checkbox-colorvar(--color-primary-foreground)Controls checkbox indicator color.
--checkbox-disabled-opacityvar(--opacity-disabled)Controls disabled opacity.
--checkbox-focus-ring-colorvar(--color-ring)Controls focus ring color.
--checkbox-focus-ring-offsetvar(--border-width-sm)Controls focus ring offset.
--checkbox-focus-ring-widthvar(--border-width-sm)Controls focus ring width.
--checkbox-icon-size-xs0.5remControls `xs` checkbox indicator icon size.
--checkbox-icon-size-sm0.625remControls `sm` checkbox indicator icon size.
--checkbox-icon-size-md0.75remControls `md` checkbox indicator icon size.
--checkbox-icon-size-lg0.875remControls `lg` checkbox indicator icon size.
--checkbox-icon-size-xl1remControls `xl` checkbox indicator icon size.
--checkbox-indicator-bgtransparentControls indicator background color.
--checkbox-indicator-bg-checkedvar(--checkbox-indicator-bg, transparent)Controls checked and indeterminate indicator background color.
--checkbox-indicator-border-colortransparentControls indicator border color.
--checkbox-indicator-border-color-checkedvar(--checkbox-indicator-border-color, transparent)Controls checked and indeterminate indicator border color.
--checkbox-indicator-border-width0Controls indicator border width.
--checkbox-indicator-radiusinheritControls indicator radius.
--checkbox-radiusvar(--radius-xs)Controls checkbox corner radius.
--checkbox-size-xs0.875remControls `xs` checkbox size.
--checkbox-size-sm1remControls `sm` checkbox size.
--checkbox-size-md1.25remControls `md` checkbox size.
--checkbox-size-lg1.5remControls `lg` checkbox size.
--checkbox-size-xl1.75remControls `xl` checkbox size.
--checkbox-transitionvar(--transition-default)Controls state transition timing.
--checkbox-group-colorvar(--color-foreground)Controls group text color.
--checkbox-group-gapvar(--spacing-2)Controls spacing between label and list.
--checkbox-group-item-gapvar(--checkbox-gap, var(--spacing-2))Controls spacing between each checkbox and item label.
--checkbox-group-item-label-colorvar(--checkbox-label-color, var(--color-foreground))Controls item label color.
--checkbox-group-item-label-font-sizevar(--checkbox-label-font-size, var(--text-sm))Controls item label font size.
--checkbox-group-item-label-font-weightvar(--checkbox-label-font-weight, var(--weight-medium))Controls item label font weight.
--checkbox-group-item-label-line-heightvar(--checkbox-label-line-height, var(--line-height-text-sm))Controls item label line height.
--checkbox-group-label-colorvar(--checkbox-group-color, var(--color-foreground))Controls group label color.
--checkbox-group-label-font-sizevar(--text-sm)Controls group label font size.
--checkbox-group-label-font-weightvar(--weight-semibold)Controls group label font weight.
--checkbox-group-label-line-heightvar(--line-height-text-sm)Controls group label line height.
--checkbox-group-list-gapvar(--spacing-2)Controls spacing between items.

Interactive variables scoped for docs preview without changing size scale tokens.

PropertyValueDefaultDescription
--checkbox-bgvar(--color-background)Controls unchecked checkbox background.
--checkbox-bg-checkedvar(--color-primary)Controls checked checkbox background.
--checkbox-bg-hovervar(--color-accent)Controls unchecked hover background.
--checkbox-border-colorvar(--color-border)Controls unchecked checkbox border color.
--checkbox-border-color-checkedvar(--color-primary)Controls checked and indeterminate border color.
--checkbox-border-widthvar(--border-width-sm)Controls checkbox border width.
--checkbox-colorvar(--color-primary-foreground)Controls checkbox indicator color.
--checkbox-disabled-opacityvar(--opacity-disabled)Controls disabled opacity.
--checkbox-focus-ring-colorvar(--color-ring)Controls focus ring color.
--checkbox-focus-ring-offsetvar(--border-width-sm)Controls focus ring offset.
--checkbox-focus-ring-widthvar(--border-width-sm)Controls focus ring width.
--checkbox-icon-size-xs0.5remControls `xs` checkbox indicator icon size.
--checkbox-icon-size-sm0.625remControls `sm` checkbox indicator icon size.
--checkbox-icon-size-md0.75remControls `md` checkbox indicator icon size.
--checkbox-icon-size-lg0.875remControls `lg` checkbox indicator icon size.
--checkbox-icon-size-xl1remControls `xl` checkbox indicator icon size.
--checkbox-indicator-bgtransparentControls indicator background color.
--checkbox-indicator-bg-checkedvar(--checkbox-indicator-bg, transparent)Controls checked and indeterminate indicator background color.
--checkbox-indicator-border-colortransparentControls indicator border color.
--checkbox-indicator-border-color-checkedvar(--checkbox-indicator-border-color, transparent)Controls checked and indeterminate indicator border color.
--checkbox-indicator-border-width0Controls indicator border width.
--checkbox-indicator-radiusinheritControls indicator radius.
--checkbox-radiusvar(--radius-xs)Controls checkbox corner radius.
--checkbox-size-xs0.875remControls `xs` checkbox size.
--checkbox-size-sm1remControls `sm` checkbox size.
--checkbox-size-md1.25remControls `md` checkbox size.
--checkbox-size-lg1.5remControls `lg` checkbox size.
--checkbox-size-xl1.75remControls `xl` checkbox size.
--checkbox-transitionvar(--transition-default)Controls state transition timing.
--checkbox-group-colorvar(--color-foreground)Controls group text color.
--checkbox-group-gapvar(--spacing-2)Controls spacing between label and list.
--checkbox-group-item-gapvar(--checkbox-gap, var(--spacing-2))Controls spacing between each checkbox and item label.
--checkbox-group-item-label-colorvar(--checkbox-label-color, var(--color-foreground))Controls item label color.
--checkbox-group-item-label-font-sizevar(--checkbox-label-font-size, var(--text-sm))Controls item label font size.
--checkbox-group-item-label-font-weightvar(--checkbox-label-font-weight, var(--weight-medium))Controls item label font weight.
--checkbox-group-item-label-line-heightvar(--checkbox-label-line-height, var(--line-height-text-sm))Controls item label line height.
--checkbox-group-label-colorvar(--checkbox-group-color, var(--color-foreground))Controls group label color.
--checkbox-group-label-font-sizevar(--text-sm)Controls group label font size.
--checkbox-group-label-font-weightvar(--weight-semibold)Controls group label font weight.
--checkbox-group-label-line-heightvar(--line-height-text-sm)Controls group label line height.
--checkbox-group-list-gapvar(--spacing-2)Controls spacing between items.

Anatomy

Checkbox Group is composed as one shared state root with optional label and list wrappers. Each row combines an interactive control and a text label; keep CheckboxGroupItemControl and CheckboxGroupItemLabel in the same CheckboxGroupItem so selection state, focus, and labeling stay aligned.

CheckboxGroup
├─ CheckboxGroupLabel
└─ CheckboxGroupList
   └─ CheckboxGroupItem
      ├─ CheckboxGroupItemControl
      │  └─ CheckboxIndicator
      │     └─ CheckboxIndicatorIcon
      └─ CheckboxGroupItemLabel
<CheckboxGroup aria-labelledby={labelId} defaultValue={['email']}>
  <CheckboxGroupLabel id={labelId}>Notification Channels</CheckboxGroupLabel>
  <CheckboxGroupList>
    <CheckboxGroupItem>
      <CheckboxGroupItemControl value="email" name="notifications" />
      <CheckboxGroupItemLabel>Email updates</CheckboxGroupItemLabel>
    </CheckboxGroupItem>
  </CheckboxGroupList>
</CheckboxGroup>
PartRole
CheckboxGroupRoot state machine. Manages selected values, disabled, allValues, and change callbacks.
CheckboxGroupLabelOptional group heading slot. Provides visible context for the entire set of options.
CheckboxGroupListOptional layout slot that contains checkbox rows and supports group-level spacing/styling.
CheckboxGroupItemOptional row wrapper that keeps one control and one text label grouped as a single option.
CheckboxGroupItemControlInteractive checkbox control for an item. Supports checkbox props and state-based styling.
CheckboxGroupItemLabelOptional text label slot associated with the item control.

CheckboxGroup does not use service slots such as portal, backdrop, or viewport. In most cases, keep behavior defaults and customize visible parts with className, classNames, and CSS variables.

Composition

Use CheckboxGroup for shared Base UI state and behavior props such as value, defaultValue, onValueChange, allValues, disabled, render, className, and state-aware style. Use allValues together with a child checkbox parent prop for select-all behavior.

CheckboxGroupLabel, CheckboxGroupList, CheckboxGroupItem, and CheckboxGroupItemLabel are layout slots. Pass className to style each visible slot. CheckboxGroupItemControl composes Checkbox, so it supports checkbox props such as size, nativeButton, render, name, value, checkedIcon, indeterminateIcon, classNames, and slotProps.

Use className for the checkbox root. Use classNames for the automatically rendered indicator slots hidden behind the default checkbox composition. Use slotProps.indicator for Base UI indicator props such as keepMounted without composing the indicator manually:

<CheckboxGroupItemControl
  className={styles.customControl}
  classNames={{
    indicator: styles.customIndicator,
    indicatorIcon: styles.customIndicatorIcon,
    checkedIcon: styles.customCheckedIcon,
    indeterminateIcon: styles.customIndeterminateIcon,
  }}
  slotProps={{
    indicator: { keepMounted: true },
  }}
/>

Examples

Sizes

Use size on CheckboxGroupItemControl to align the controls with different form densities.

Control Size
import {  CheckboxGroup,  CheckboxGroupItem,  CheckboxGroupItemControl,  CheckboxGroupItemLabel,  CheckboxGroupLabel,  CheckboxGroupList,} from "moduix";import { useId } from "react";export function CheckboxGroupSizesDemo() {  const labelId = useId();  return (    <CheckboxGroup aria-labelledby={labelId} defaultValue={["md"]}>      <CheckboxGroupLabel id={labelId}>Control Size</CheckboxGroupLabel>      <CheckboxGroupList>        {options.map((option) => (          <CheckboxGroupItem key={option.value}>            <CheckboxGroupItemControl value={option.value} size={option.value} />            <CheckboxGroupItemLabel>{option.label}</CheckboxGroupItemLabel>          </CheckboxGroupItem>        ))}      </CheckboxGroupList>    </CheckboxGroup>  );}
const options = [  { value: "xs", label: "Extra-small" },  { value: "sm", label: "Small" },  { value: "md", label: "Medium" },  { value: "lg", label: "Large" },  { value: "xl", label: "Extra-large" },] as const;

Controlled

Control value from React state when the selected options need to coordinate with other UI.

Active Alerts
Current value: push
import {  CheckboxGroup,  CheckboxGroupItem,  CheckboxGroupItemControl,  CheckboxGroupItemLabel,  CheckboxGroupLabel,  CheckboxGroupList,} from "moduix";import { useId, useState } from "react";export function ControlledCheckboxGroupDemo() {  const labelId = useId();  const [value, setValue] = useState(["push"] as string[]);  return (    <div className={styles.wrapper}>      <CheckboxGroup aria-labelledby={labelId} value={value} onValueChange={setValue}>        <CheckboxGroupLabel id={labelId}>Active Alerts</CheckboxGroupLabel>        <CheckboxGroupList>          {options.map((option) => (            <CheckboxGroupItem key={option.value}>              <CheckboxGroupItemControl value={option.value} name="alerts" />              <CheckboxGroupItemLabel>{option.label}</CheckboxGroupItemLabel>            </CheckboxGroupItem>          ))}        </CheckboxGroupList>      </CheckboxGroup>      <span className={styles.hint}>Current value: {value.join(", ") || "none"}</span>    </div>  );}
.wrapper {  display: flex;  flex-direction: column;  align-items: flex-start;  gap: var(--spacing-2);}.hint {  color: var(--color-muted-foreground);  font-size: var(--text-xs);  line-height: var(--line-height-text-xs);}
const options = [  { value: "email", label: "Email updates" },  { value: "push", label: "Push notifications" },  { value: "sms", label: "SMS alerts" },];

Disabled

Use disabled on the group to prevent interaction with every checkbox in the group.

Disabled Settings
import {  CheckboxGroup,  CheckboxGroupItem,  CheckboxGroupItemControl,  CheckboxGroupItemLabel,  CheckboxGroupLabel,  CheckboxGroupList,} from "moduix";import { useId } from "react";export function DisabledCheckboxGroupDemo() {  const labelId = useId();  return (    <CheckboxGroup aria-labelledby={labelId} defaultValue={["push"]} disabled>      <CheckboxGroupLabel id={labelId}>Disabled Settings</CheckboxGroupLabel>      <CheckboxGroupList>        {options.map((option) => (          <CheckboxGroupItem key={option.value}>            <CheckboxGroupItemControl value={option.value} name="disabled-settings" />            <CheckboxGroupItemLabel>{option.label}</CheckboxGroupItemLabel>          </CheckboxGroupItem>        ))}      </CheckboxGroupList>    </CheckboxGroup>  );}
const options = [  { value: "email", label: "Email updates" },  { value: "push", label: "Push notifications" },  { value: "sms", label: "SMS alerts" },];

Parent Checkbox

Use allValues with a parent checkbox to create a select-all control that enters the indeterminate state when only some child options are checked.

Fruits
import {  CheckboxGroup,  CheckboxGroupItem,  CheckboxGroupItemControl,  CheckboxGroupItemLabel,  CheckboxGroupLabel,  CheckboxGroupList,} from "moduix";import { useId, useState } from "react";export function ParentCheckboxGroupDemo() {  const labelId = useId();  const [value, setValue] = useState([] as string[]);  return (    <CheckboxGroup      aria-labelledby={labelId}      value={value}      onValueChange={setValue}      allValues={fruitValues}    >      <CheckboxGroupLabel id={labelId}>Fruits</CheckboxGroupLabel>      <CheckboxGroupList>        <CheckboxGroupItem>          <CheckboxGroupItemControl parent />          <CheckboxGroupItemLabel>Select all</CheckboxGroupItemLabel>        </CheckboxGroupItem>        {options.map((option) => (          <CheckboxGroupItem key={option.value}>            <CheckboxGroupItemControl value={option.value} />            <CheckboxGroupItemLabel>{option.label}</CheckboxGroupItemLabel>          </CheckboxGroupItem>        ))}      </CheckboxGroupList>    </CheckboxGroup>  );}
const options = [  { value: "apple", label: "Apple" },  { value: "orange", label: "Orange" },  { value: "pear", label: "Pear" },];const fruitValues = options.map((option) => option.value);

Custom Icon

Pass checkedIcon, indeterminateIcon, indicator, or custom children to CheckboxGroupItemControl to use any icon from your application or icon library.

Custom Indicators
import {  CheckboxGroup,  CheckboxGroupItem,  CheckboxGroupItemControl,  CheckboxGroupItemLabel,  CheckboxGroupLabel,  CheckboxGroupList,} from "moduix";import { useId } from "react";function CustomPlusIcon() {  return (    <svg viewBox="0 0 10 10" fill="none" aria-hidden="true" focusable="false">      <path        d="M5 1.5V8.5M1.5 5H8.5"        stroke="currentColor"        strokeWidth="1.8"        strokeLinecap="round"      />    </svg>  );}export function CustomIconCheckboxGroupDemo() {  const labelId = useId();  return (    <CheckboxGroup aria-labelledby={labelId} defaultValue={["email"]}>      <CheckboxGroupLabel id={labelId}>Custom Indicators</CheckboxGroupLabel>      <CheckboxGroupList>        {options.map((option) => (          <CheckboxGroupItem key={option.value}>            <CheckboxGroupItemControl              value={option.value}              name="custom-indicators"              checkedIcon={<CustomPlusIcon />}            />            <CheckboxGroupItemLabel>{option.label}</CheckboxGroupItemLabel>          </CheckboxGroupItem>        ))}      </CheckboxGroupList>    </CheckboxGroup>  );}
const options = [  { value: "email", label: "Email updates" },  { value: "push", label: "Push notifications" },  { value: "sms", label: "SMS alerts" },];

Custom Styles

Pass className to the group, label, list, item, control, and item label slots. Use classNames on CheckboxGroupItemControl for internal checkbox slots such as indicator.

Styled Channels
import {  CheckboxGroup,  CheckboxGroupItem,  CheckboxGroupItemControl,  CheckboxGroupItemLabel,  CheckboxGroupLabel,  CheckboxGroupList,} from "moduix";import { useId } from "react";export function CustomStylesCheckboxGroupDemo() {  const labelId = useId();  return (    <CheckboxGroup      aria-labelledby={labelId}      defaultValue={["email"]}      className={styles.customGroup}    >      <CheckboxGroupLabel id={labelId} className={styles.customLabel}>        Styled Channels      </CheckboxGroupLabel>      <CheckboxGroupList className={styles.customList}>        {options.map((option) => (          <CheckboxGroupItem key={option.value} className={styles.customItem}>            <CheckboxGroupItemControl              value={option.value}              name="styled-notifications"              className={styles.customControl}              classNames={{ indicator: styles.customIndicator }}            />            <CheckboxGroupItemLabel className={styles.customItemLabel}>              {option.label}            </CheckboxGroupItemLabel>          </CheckboxGroupItem>        ))}      </CheckboxGroupList>    </CheckboxGroup>  );}
.customGroup,.customList,.customItem {  gap: var(--spacing-3);}.customLabel,.customItemLabel {  color: var(--color-primary);}.customControl {  border-color: var(--color-primary);  &[data-checked] {    background-color: var(--color-primary);  }}.customIndicator {  color: var(--color-primary-foreground);}
const options = [  { value: "email", label: "Email updates" },  { value: "push", label: "Push notifications" },  { value: "sms", label: "SMS alerts" },];

Field Composition

Use CheckboxField, Checkbox, and CheckboxLabel directly inside CheckboxGroup when you want a compact enclosing-label composition.

Channels
import {  Checkbox,  CheckboxField,  CheckboxGroup,  CheckboxGroupLabel,  CheckboxGroupList,  CheckboxLabel,} from "moduix";import { useId } from "react";export function CheckboxGroupFieldCompositionDemo() {  const labelId = useId();  return (    <CheckboxGroup aria-labelledby={labelId} defaultValue={["email"]}>      <CheckboxGroupLabel id={labelId}>Channels</CheckboxGroupLabel>      <CheckboxGroupList>        {options.map((option) => (          <CheckboxField key={option.value}>            <Checkbox value={option.value} name="field-composition" />            <CheckboxLabel>{option.label}</CheckboxLabel>          </CheckboxField>        ))}      </CheckboxGroupList>    </CheckboxGroup>  );}
const options = [  { value: "email", label: "Email updates" },  { value: "push", label: "Push notifications" },  { value: "sms", label: "SMS alerts" },];

Sibling Label

Use nativeButton with render={<button />} for the sibling label pattern with htmlFor and id.

Channels
import { CheckboxGroup, CheckboxGroupItemControl } from "moduix";import { useId } from "react";export function SiblingLabelCheckboxGroupDemo() {  const id = useId();  const labelId = useId();  return (    <div className={styles.siblingRow}>      <div id={labelId} className={styles.hint}>        Channels      </div>      <CheckboxGroup defaultValue={["email"]} aria-labelledby={labelId}>        <CheckboxGroupItemControl          nativeButton          render={<button />}          id={id}          value="email"          name="sibling-notifications"        />      </CheckboxGroup>      <label htmlFor={id} className={styles.label}>        Email updates      </label>    </div>  );}
.siblingRow {  display: flex;  align-items: center;  gap: var(--checkbox-gap, var(--spacing-2));}.hint {  color: var(--color-muted-foreground);  font-size: var(--text-xs);  line-height: var(--line-height-text-xs);}.label {  color: var(--checkbox-label-color, var(--color-foreground));  font-size: var(--checkbox-label-font-size, var(--text-sm));  font-weight: var(--checkbox-label-font-weight, var(--weight-medium));  line-height: var(--checkbox-label-line-height, var(--line-height-text-sm));}

Form Integration

Use Field and Fieldset when the group needs form naming, validation state, or shared labeling.

Notification Channels
import {  Checkbox,  CheckboxGroup,  CheckboxLabel,  Field,  FieldItem,  FieldLabel,  Fieldset,  FieldsetLegend,} from "moduix";export function CheckboxGroupFormIntegrationDemo() {  return (    <Field name="notificationChannels">      <Fieldset render={<CheckboxGroup defaultValue={["email"]} />}>        <FieldsetLegend>Notification Channels</FieldsetLegend>        {options.map((option) => (          <FieldItem key={option.value}>            <FieldLabel>              <Checkbox value={option.value} />              <CheckboxLabel>{option.label}</CheckboxLabel>            </FieldLabel>          </FieldItem>        ))}      </Fieldset>    </Field>  );}
const options = [  { value: "email", label: "Email updates" },  { value: "push", label: "Push notifications" },  { value: "sms", label: "SMS alerts" },];

On this page