Components
- Accordion
- Alert
- Alert Dialog
- Autocomplete
- Avatar
- Badge
- Breadcrumb
- Button
- Card
- Checkbox
- Checkbox Group
- Collapsible
- Combobox
- Dialog
- Field
- Fieldset
- Form
- Frame
- Group
- Input
- Label
- Menu
- Meter
- Number Field
- Pagination
- Popover
- Preview Card
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Slider
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Toolbar
- Tooltip
Resources
Checkbox Group
Provides shared state to a series of checkboxes.
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="vite" />
Vite
</Label>
<Label>
<Checkbox value="astro" />
Astro
</Label>
</CheckboxGroup>
)
}
Installation
pnpm dlx shadcn@latest add https://coss.com/ui/r/checkbox-group.json
Usage
import { Checkbox } from "@/components/ui/checkbox"
import { CheckboxGroup } from "@/components/ui/checkbox-group"
<CheckboxGroup>
<Label>
<Checkbox defaultChecked />
Next.js
</Label>
<Label>
<Checkbox />
Vite
</Label>
<Label>
<Checkbox />
Astro
</Label>
</CheckboxGroup>
Examples
For accessible group labelling and validation, prefer wrapping checkbox groups with Field
and Fieldset
. See the related example: Checkbox group field.
With Disabled Item
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="vite" disabled />
Vite
</Label>
<Label>
<Checkbox value="astro" />
Astro
</Label>
</CheckboxGroup>
)
}
Parent Checkbox
"use client"
import * as React 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: "vite", name: "Vite" },
{ id: "astro", name: "Astro" },
]
export function CheckboxGroupParentDemo() {
const [value, setValue] = React.useState<string[]>([])
return (
<CheckboxGroup
aria-labelledby="frameworks-caption"
value={value}
onValueChange={setValue}
allValues={frameworks.map((framework) => framework.id)}
>
<Label id="frameworks-caption">
<Checkbox name="frameworks" parent />
Frameworks
</Label>
{frameworks.map((framework) => (
<Label key={framework.id} className="ms-4">
<Checkbox value={framework.id} />
{framework.name}
</Label>
))}
</CheckboxGroup>
)
}
Nested Parent Checkbox
"use client"
import * as React 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 CheckboxGroupNestedParentDemo() {
const [mainValue, setMainValue] = React.useState<string[]>([])
const [managementValue, setManagementValue] = React.useState<string[]>([])
const managementIsPartial =
managementValue.length > 0 &&
managementValue.length !== userManagementPermissions.length
return (
<CheckboxGroup
aria-labelledby="user-permissions-caption"
value={mainValue}
onValueChange={(value) => {
if (value.includes("manage-users")) {
setManagementValue(userManagementPermissions.map((p) => p.id))
} else if (
managementValue.length === userManagementPermissions.length
) {
setManagementValue([])
}
setMainValue(value)
}}
allValues={mainPermissions.map((p) => p.id)}
>
<Label id="user-permissions-caption">
<Checkbox parent indeterminate={managementIsPartial} />
User Permissions
</Label>
{mainPermissions
.filter((p) => p.id !== "manage-users")
.map((p) => (
<Label key={p.id} className="ms-4">
<Checkbox value={p.id} />
{p.name}
</Label>
))}
<CheckboxGroup
aria-labelledby="manage-users-caption"
value={managementValue}
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)
}}
allValues={userManagementPermissions.map((p) => p.id)}
className="ms-4"
>
<Label id="manage-users-caption">
<Checkbox parent />
Manage Users
</Label>
{userManagementPermissions.map((p) => (
<Label key={p.id} className="ms-4">
<Checkbox value={p.id} />
{p.name}
</Label>
))}
</CheckboxGroup>
</CheckboxGroup>
)
}
Form Integration
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { CheckboxGroup } from "@/components/ui/checkbox-group"
import { Field, FieldLabel } from "@/components/ui/field"
import { Fieldset, FieldsetLegend } from "@/components/ui/fieldset"
import { Form } from "@/components/ui/form"
export function CheckboxGroupFormDemo() {
const [loading, setLoading] = React.useState(false)
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const formData = new FormData(e.currentTarget)
setLoading(true)
await new Promise((r) => setTimeout(r, 800))
setLoading(false)
const frameworks = formData.getAll("frameworks") as string[]
alert(`Selected: ${frameworks.join(", ") || "none"}`)
}
return (
<Form onSubmit={onSubmit} className="max-w-[160px]">
<Field
name="frameworks"
className="gap-4"
render={(props) => <Fieldset {...props} />}
>
<FieldsetLegend className="text-sm font-medium">
Frameworks
</FieldsetLegend>
<CheckboxGroup defaultValue={["next"]} disabled={loading}>
<FieldLabel>
<Checkbox value="next" />
Next.js
</FieldLabel>
<FieldLabel>
<Checkbox value="vite" />
Vite
</FieldLabel>
<FieldLabel>
<Checkbox value="astro" />
Astro
</FieldLabel>
</CheckboxGroup>
</Field>
<Button type="submit" disabled={loading}>
Submit
</Button>
</Form>
)
}