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.
Basic
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.
| Property | Default | Description |
|---|---|---|
| --checkbox-bg | var(--color-background) | Controls unchecked checkbox background. |
| --checkbox-bg-checked | var(--color-primary) | Controls checked checkbox background. |
| --checkbox-bg-hover | var(--color-accent) | Controls unchecked hover background. |
| --checkbox-border-color | var(--color-border) | Controls unchecked checkbox border color. |
| --checkbox-border-color-checked | var(--color-primary) | Controls checked and indeterminate border color. |
| --checkbox-border-width | var(--border-width-sm) | Controls checkbox border width. |
| --checkbox-color | var(--color-primary-foreground) | Controls checkbox indicator color. |
| --checkbox-disabled-opacity | var(--opacity-disabled) | Controls disabled opacity. |
| --checkbox-focus-ring-color | var(--color-ring) | Controls focus ring color. |
| --checkbox-focus-ring-offset | var(--border-width-sm) | Controls focus ring offset. |
| --checkbox-focus-ring-width | var(--border-width-sm) | Controls focus ring width. |
| --checkbox-icon-size-xs | 0.5rem | Controls `xs` checkbox indicator icon size. |
| --checkbox-icon-size-sm | 0.625rem | Controls `sm` checkbox indicator icon size. |
| --checkbox-icon-size-md | 0.75rem | Controls `md` checkbox indicator icon size. |
| --checkbox-icon-size-lg | 0.875rem | Controls `lg` checkbox indicator icon size. |
| --checkbox-icon-size-xl | 1rem | Controls `xl` checkbox indicator icon size. |
| --checkbox-indicator-bg | transparent | Controls indicator background color. |
| --checkbox-indicator-bg-checked | var(--checkbox-indicator-bg, transparent) | Controls checked and indeterminate indicator background color. |
| --checkbox-indicator-border-color | transparent | Controls indicator border color. |
| --checkbox-indicator-border-color-checked | var(--checkbox-indicator-border-color, transparent) | Controls checked and indeterminate indicator border color. |
| --checkbox-indicator-border-width | 0 | Controls indicator border width. |
| --checkbox-indicator-radius | inherit | Controls indicator radius. |
| --checkbox-radius | var(--radius-xs) | Controls checkbox corner radius. |
| --checkbox-size-xs | 0.875rem | Controls `xs` checkbox size. |
| --checkbox-size-sm | 1rem | Controls `sm` checkbox size. |
| --checkbox-size-md | 1.25rem | Controls `md` checkbox size. |
| --checkbox-size-lg | 1.5rem | Controls `lg` checkbox size. |
| --checkbox-size-xl | 1.75rem | Controls `xl` checkbox size. |
| --checkbox-transition | var(--transition-default) | Controls state transition timing. |
| --checkbox-group-color | var(--color-foreground) | Controls group text color. |
| --checkbox-group-gap | var(--spacing-2) | Controls spacing between label and list. |
| --checkbox-group-item-gap | var(--checkbox-gap, var(--spacing-2)) | Controls spacing between each checkbox and item label. |
| --checkbox-group-item-label-color | var(--checkbox-label-color, var(--color-foreground)) | Controls item label color. |
| --checkbox-group-item-label-font-size | var(--checkbox-label-font-size, var(--text-sm)) | Controls item label font size. |
| --checkbox-group-item-label-font-weight | var(--checkbox-label-font-weight, var(--weight-medium)) | Controls item label font weight. |
| --checkbox-group-item-label-line-height | var(--checkbox-label-line-height, var(--line-height-text-sm)) | Controls item label line height. |
| --checkbox-group-label-color | var(--checkbox-group-color, var(--color-foreground)) | Controls group label color. |
| --checkbox-group-label-font-size | var(--text-sm) | Controls group label font size. |
| --checkbox-group-label-font-weight | var(--weight-semibold) | Controls group label font weight. |
| --checkbox-group-label-line-height | var(--line-height-text-sm) | Controls group label line height. |
| --checkbox-group-list-gap | var(--spacing-2) | Controls spacing between items. |
Interactive variables scoped for docs preview without changing size scale tokens.
| Property | Value | Default | Description |
|---|---|---|---|
| --checkbox-bg | var(--color-background) | Controls unchecked checkbox background. | |
| --checkbox-bg-checked | var(--color-primary) | Controls checked checkbox background. | |
| --checkbox-bg-hover | var(--color-accent) | Controls unchecked hover background. | |
| --checkbox-border-color | var(--color-border) | Controls unchecked checkbox border color. | |
| --checkbox-border-color-checked | var(--color-primary) | Controls checked and indeterminate border color. | |
| --checkbox-border-width | var(--border-width-sm) | Controls checkbox border width. | |
| --checkbox-color | var(--color-primary-foreground) | Controls checkbox indicator color. | |
| --checkbox-disabled-opacity | var(--opacity-disabled) | Controls disabled opacity. | |
| --checkbox-focus-ring-color | var(--color-ring) | Controls focus ring color. | |
| --checkbox-focus-ring-offset | var(--border-width-sm) | Controls focus ring offset. | |
| --checkbox-focus-ring-width | var(--border-width-sm) | Controls focus ring width. | |
| --checkbox-icon-size-xs | 0.5rem | Controls `xs` checkbox indicator icon size. | |
| --checkbox-icon-size-sm | 0.625rem | Controls `sm` checkbox indicator icon size. | |
| --checkbox-icon-size-md | 0.75rem | Controls `md` checkbox indicator icon size. | |
| --checkbox-icon-size-lg | 0.875rem | Controls `lg` checkbox indicator icon size. | |
| --checkbox-icon-size-xl | 1rem | Controls `xl` checkbox indicator icon size. | |
| --checkbox-indicator-bg | transparent | Controls indicator background color. | |
| --checkbox-indicator-bg-checked | var(--checkbox-indicator-bg, transparent) | Controls checked and indeterminate indicator background color. | |
| --checkbox-indicator-border-color | transparent | Controls indicator border color. | |
| --checkbox-indicator-border-color-checked | var(--checkbox-indicator-border-color, transparent) | Controls checked and indeterminate indicator border color. | |
| --checkbox-indicator-border-width | 0 | Controls indicator border width. | |
| --checkbox-indicator-radius | inherit | Controls indicator radius. | |
| --checkbox-radius | var(--radius-xs) | Controls checkbox corner radius. | |
| --checkbox-size-xs | 0.875rem | Controls `xs` checkbox size. | |
| --checkbox-size-sm | 1rem | Controls `sm` checkbox size. | |
| --checkbox-size-md | 1.25rem | Controls `md` checkbox size. | |
| --checkbox-size-lg | 1.5rem | Controls `lg` checkbox size. | |
| --checkbox-size-xl | 1.75rem | Controls `xl` checkbox size. | |
| --checkbox-transition | var(--transition-default) | Controls state transition timing. | |
| --checkbox-group-color | var(--color-foreground) | Controls group text color. | |
| --checkbox-group-gap | var(--spacing-2) | Controls spacing between label and list. | |
| --checkbox-group-item-gap | var(--checkbox-gap, var(--spacing-2)) | Controls spacing between each checkbox and item label. | |
| --checkbox-group-item-label-color | var(--checkbox-label-color, var(--color-foreground)) | Controls item label color. | |
| --checkbox-group-item-label-font-size | var(--checkbox-label-font-size, var(--text-sm)) | Controls item label font size. | |
| --checkbox-group-item-label-font-weight | var(--checkbox-label-font-weight, var(--weight-medium)) | Controls item label font weight. | |
| --checkbox-group-item-label-line-height | var(--checkbox-label-line-height, var(--line-height-text-sm)) | Controls item label line height. | |
| --checkbox-group-label-color | var(--checkbox-group-color, var(--color-foreground)) | Controls group label color. | |
| --checkbox-group-label-font-size | var(--text-sm) | Controls group label font size. | |
| --checkbox-group-label-font-weight | var(--weight-semibold) | Controls group label font weight. | |
| --checkbox-group-label-line-height | var(--line-height-text-sm) | Controls group label line height. | |
| --checkbox-group-list-gap | var(--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>| Part | Role |
|---|---|
CheckboxGroup | Root state machine. Manages selected values, disabled, allValues, and change callbacks. |
CheckboxGroupLabel | Optional group heading slot. Provides visible context for the entire set of options. |
CheckboxGroupList | Optional layout slot that contains checkbox rows and supports group-level spacing/styling. |
CheckboxGroupItem | Optional row wrapper that keeps one control and one text label grouped as a single option. |
CheckboxGroupItemControl | Interactive checkbox control for an item. Supports checkbox props and state-based styling. |
CheckboxGroupItemLabel | Optional 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.
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.
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.
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.
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.
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.
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.
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.
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.
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" },];