---
title: Checkbox Group
description: Provides shared state to a series of checkboxes.
links:
  doc: https://base-ui.com/react/components/checkbox-group
  anatomy: https://base-ui.com/react/components/checkbox-group#anatomy
  api: https://base-ui.com/react/components/checkbox-group#api-reference
---

```tsx
import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

export function CheckboxGroupDemo() {
  return (
    <CheckboxGroup aria-label="Select frameworks" defaultValue={["next"]}>
      <Label>
        <Checkbox value="next" />
        Next.js
      </Label>
      <Label>
        <Checkbox value="solid" />
        Solid Start
      </Label>
      <Label>
        <Checkbox value="angular" />
        Angular
      </Label>
    </CheckboxGroup>
  );
}
```

## Installation

<ComponentSource name="checkbox-group" title="components/ui/checkbox-group.tsx" />

## Usage

```tsx
import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";
```

```tsx
<CheckboxGroup>
  <Label>
    <Checkbox defaultChecked />
    Next.js
  </Label>
  <Label>
    <Checkbox />
    Vite
  </Label>
  <Label>
    <Checkbox />
    Astro
  </Label>
</CheckboxGroup>
```

## Examples

### Labeling checkbox group

Label the group with `aria-labelledby` and a sibling label element:

```tsx
import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

export function CheckboxGroupDemo() {
  return (
    <div className="flex flex-col items-start gap-4">
      <Label id="frameworks-label">Select frameworks</Label>
      <CheckboxGroup aria-labelledby="frameworks-label" defaultValue={["next"]}>
        <Label>
          <Checkbox value="next" />
          Next.js
        </Label>
        <Label>
          <Checkbox value="solid" />
          Solid Start
        </Label>
        <Label>
          <Checkbox value="angular" />
          Angular
        </Label>
      </CheckboxGroup>
    </div>
  );
}
```

### Disabled

```tsx
import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

export function CheckboxGroupDemo() {
  return (
    <div className="flex flex-col items-start gap-4">
      <Label id="frameworks-label">Select frameworks</Label>
      <CheckboxGroup aria-labelledby="frameworks-label" defaultValue={["next"]} disabled>
        <Label>
          <Checkbox value="next" />
          Next.js
        </Label>
        <Label>
          <Checkbox value="solid" />
          Solid Start
        </Label>
        <Label>
          <Checkbox value="angular" />
          Angular
        </Label>
      </CheckboxGroup>
    </div>
  );
}
```

### With disabled item

```tsx
import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

export function CheckboxGroupDemo() {
  return (
    <div className="flex flex-col items-start gap-4">
      <Label id="frameworks-label">Select frameworks</Label>
      <CheckboxGroup aria-labelledby="frameworks-label" defaultValue={["next"]}>
        <div className="flex items-center gap-2">
          <Checkbox id="next-checkbox" value="next" className="peer" />
          <Label htmlFor="next-checkbox" className="peer-data-disabled:opacity-50">
            Next.js
          </Label>
        </div>
        <div className="flex items-center gap-2">
          <Checkbox id="solid-checkbox" value="solid" disabled className="peer" />
          <Label htmlFor="solid-checkbox" className="peer-data-disabled:opacity-50">
            Solid Start
          </Label>
        </div>
        <div className="flex items-center gap-2">
          <Checkbox id="angular-checkbox" value="angular" className="peer" />
          <Label htmlFor="angular-checkbox" className="peer-data-disabled:opacity-50">
            Angular
          </Label>
        </div>
      </CheckboxGroup>
    </div>
  );
}
```

### Controlled

```tsx
"use client";

import { useState } from "react";

import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

const frameworks = [
  { id: "next", name: "Next.js" },
  { id: "solid", name: "Solid Start" },
  { id: "angular", name: "Angular" },
];

export function CheckboxGroupDemo() {
  const [value, setValue] = useState<string[]>(["solid"]);

  return (
    <div className="flex w-full max-w-sm flex-col items-center gap-4">
      <CheckboxGroup aria-labelledby="frameworks" onValueChange={setValue} value={value}>
        <Label id="frameworks">Select Frameworks</Label>
        {frameworks.map((framework) => (
          <Label className="ms-4" key={framework.id}>
            <Checkbox value={framework.id} />
            {framework.name}
          </Label>
        ))}
      </CheckboxGroup>
      <pre className="rounded-lg bg-muted px-3 py-2 text-sm">
        <code>{JSON.stringify(value)}</code>
      </pre>
    </div>
  );
}
```

### Parent checkbox

```tsx
"use client";

import { useState } from "react";

import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

const frameworks = [
  { id: "next", name: "Next.js" },
  { id: "solid", name: "Solid Start" },
  { id: "angular", name: "Angular" },
];

export function CheckboxGroupDemo() {
  const [value, setValue] = useState<string[]>([]);

  return (
    <CheckboxGroup
      allValues={frameworks.map((framework) => framework.id)}
      aria-labelledby="frameworks-caption"
      onValueChange={setValue}
      value={value}
    >
      <Label id="frameworks-caption">
        <Checkbox name="frameworks" parent />
        Frameworks
      </Label>
      {frameworks.map((framework) => (
        <Label className="ms-4" key={framework.id}>
          <Checkbox value={framework.id} />
          {framework.name}
        </Label>
      ))}
    </CheckboxGroup>
  );
}
```

### Nested parent checkbox

```tsx
"use client";

import { useState } from "react";

import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Label } from "@/components/ui/label";

const mainPermissions = [
  { id: "view-dashboard", name: "View Dashboard" },
  { id: "manage-users", name: "Manage Users" },
  { id: "access-reports", name: "Access Reports" },
];
const userManagementPermissions = [
  { id: "create-user", name: "Create User" },
  { id: "edit-user", name: "Edit User" },
  { id: "delete-user", name: "Delete User" },
  { id: "assign-roles", name: "Assign Roles" },
];

export function CheckboxGroupDemo() {
  const [mainValue, setMainValue] = useState<string[]>([]);
  const [managementValue, setManagementValue] = useState<string[]>([]);

  const managementIsPartial =
    managementValue.length > 0 && managementValue.length !== userManagementPermissions.length;

  return (
    <CheckboxGroup
      allValues={mainPermissions.map((p) => p.id)}
      aria-labelledby="user-permissions"
      onValueChange={(value) => {
        if (value.includes("manage-users")) {
          setManagementValue(userManagementPermissions.map((p) => p.id));
        } else if (managementValue.length === userManagementPermissions.length) {
          setManagementValue([]);
        }
        setMainValue(value);
      }}
      value={mainValue}
    >
      <Label id="user-permissions">
        <Checkbox indeterminate={managementIsPartial} parent />
        User Permissions
      </Label>
      {mainPermissions
        .filter((p) => p.id !== "manage-users")
        .map((p) => (
          <Label className="ms-4" key={p.id}>
            <Checkbox value={p.id} />
            {p.name}
          </Label>
        ))}
      <CheckboxGroup
        allValues={userManagementPermissions.map((p) => p.id)}
        aria-labelledby="manage-users"
        className="ms-4"
        onValueChange={(value) => {
          if (value.length === userManagementPermissions.length) {
            setMainValue((prev) => Array.from(new Set([...prev, "manage-users"])));
          } else {
            setMainValue((prev) => prev.filter((v) => v !== "manage-users"));
          }
          setManagementValue(value);
        }}
        value={managementValue}
      >
        <Label id="manage-users">
          <Checkbox parent />
          Manage Users
        </Label>
        {userManagementPermissions.map((p) => (
          <Label className="ms-4" key={p.id}>
            <Checkbox value={p.id} />
            {p.name}
          </Label>
        ))}
      </CheckboxGroup>
    </CheckboxGroup>
  );
}
```
