Checkbox Group
Shared state for a set of checkboxes, with first-class "select all" — parent, mixed, and the whole-set toggle, built on Base UI Checkbox Group.
- Status
- Since
0.7.0- Accessibility pattern
- grouped checkboxes
Last updated
Install
Add Checkbox Group from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.
pnpm dlx shadcn@latest add @vegastack/checkbox-groupUsage
import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";
const ALL = ["read", "write", "admin"];
<CheckboxGroup defaultValue={["read"]} allValues={ALL} aria-labelledby="perms">
<Label>
<Checkbox parent /> All permissions
</Label>
<Label>
<Checkbox value="read" /> Read
</Label>
<Label>
<Checkbox value="write" /> Write
</Label>
<Label>
<Checkbox value="admin" /> Admin
</Label>
</CheckboxGroup>;Built on Base UI Checkbox Group. The group
owns the array of ticked values; each child is a plain
Checkbox carrying a value. There is no CheckboxGroupItem — a
wrapper whose only job is to forward every prop would earn nothing.
Pass allValues and mark one child parent to get the select-all row. Base UI ticks and unticks
the whole set from it and drives its mixed (indeterminate) state when only some children are on —
the arithmetic that used to be written by hand on every settings page and in every grid header.
Name the group. It renders no label of its own, so give it a wrapping
FieldSet + FieldLegend (the strongest form, and the one to prefer in a
form) or an aria-labelledby pointing at a heading. An unnamed group announces as a bare list of
checkboxes with no idea what they belong to.
Anatomy
<FieldSet>
<FieldLegend>Permissions</FieldLegend>
<CheckboxGroup value={value} onValueChange={setValue} allValues={ALL}>
<Label>
<Checkbox parent /> All permissions
</Label>
<Label>
<Checkbox value="read" /> Read
</Label>
</CheckboxGroup>
</FieldSet>Examples
Select all
The parent ticks and unticks every value in allValues, and reads mixed while only some children
are on.
States
Nothing ticked, some ticked, all ticked — the parent's own state is derived, never assigned.
Uncontrolled
Omit value/onValueChange and pass defaultValue. Without allValues there is no parent, which
is the right shape for a plain list of independent options.
Disabled
disabled on the group disables every child, the parent included. The boxes stay hoverable so a
Tooltip can explain why they are unavailable.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
allValues | string[] | — | Every value in the group. Set it to enable a parent checkbox: the parent ticks and unticks
the whole set and shows the mixed (indeterminate) state when only some children are on.
Without it a parent checkbox has nothing to compute against. |
defaultValue | string[] | — | Values ticked initially (uncontrolled). Use value instead for a controlled group. |
disabled | boolean | false | Disables the whole group, every child included. |
onValueChange | ((value: string[], eventDetails: BaseCheckboxGroup.ChangeEventDetails) => void) | — | Called with the next array of ticked values whenever a child is toggled, plus Base UI's event details. |
value | string[] | — | Values of the checkboxes that are ticked (controlled). Pair with onValueChange.
Required — along with allValues — for a parent checkbox to work. |
Data attributes and CSS variables on CheckboxGroup
| Attribute | Values |
|---|---|
data-slot | "checkbox-group" |
Accessibility
- The group renders a
<div>with no implicit name. Wrap it in aFieldSet/FieldLegend, or give itaria-labelledby. - The parent checkbox exposes
aria-checked="mixed"while only some children are ticked, and"true"/"false"at the ends. - Every checkbox is its own tab stop — a checkbox group is not a roving-tabindex collection, unlike
a
RadioGroup, because the options are not mutually exclusive. disabledon the group removes every child from the tab order.
| Key | Action |
|---|---|
| Tab | Move focus to the next checkbox in the group. |
| Space | Toggle the focused checkbox — or, on the parent, the whole set. |
| Contract | States tested |
|---|---|
| Behaviour | default, checked, disabled, indeterminate |
| Accessibility | checked, focus-visible, labeled, semantic-html |
| Visual | default, disabled, dark |