Siteplane UI

Checkbox Group

Choose any number of related options.

Markdown
"use client";

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

export default function Example() {
  return (
    <CheckboxGroup aria-label="Notification channels" defaultValue={["email"]}>
      <Label>
        <Checkbox value="email" />
        Email
      </Label>
      <Label>
        <Checkbox value="push" />
        Push notifications
      </Label>
      <Label>
        <Checkbox value="sms" />
        SMS
      </Label>
    </CheckboxGroup>
  );
}

Installation

pnpm dlx shadcn@4.18.0 add @siteplane/checkbox-group

Complete the one-time setup first. Registry JSON lists source files and dependencies.

For this page’s examples, also install:

pnpm dlx shadcn@4.18.0 add @siteplane/button @siteplane/checkbox @siteplane/fieldset @siteplane/form @siteplane/input @siteplane/label

Field is installed with Input.

Usage

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

<CheckboxGroup aria-label="Notification channels" defaultValue={["email"]}>
  <Label>
    <Checkbox value="email" />
    Email
  </Label>
  <Label>
    <Checkbox value="sms" />
    SMS
  </Label>
</CheckboxGroup>;

Composition

CheckboxGroup
├── Label + Checkbox
└── Label + Checkbox

Controlled selection

Pass value and onValueChange to own the selected values. Each checkbox needs a unique value; a disabled item keeps its state.

"use client";

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

export default function Example() {
  const [value, setValue] = useState<string[]>(["name", "status"]);
  return (
    <CheckboxGroup
      aria-label="Visible columns"
      onValueChange={setValue}
      value={value}
    >
      <Label>
        <Checkbox disabled value="name" />
        Name
      </Label>
      <Label>
        <Checkbox value="status" />
        Status
      </Label>
      <Label>
        <Checkbox value="owner" />
        Owner
      </Label>
      <Label>
        <Checkbox value="updated" />
        Last updated
      </Label>
    </CheckboxGroup>
  );
}

Parent checkbox

Add a checkbox with parent and list every item value in allValues. The parent checks or clears all items and shows the mixed state when only some are selected.

"use client";

import { useId, useState } from "react";
import { Checkbox } from "@/siteplane/components/checkbox";
import { CheckboxGroup } from "@/siteplane/components/checkbox-group";
import { Label } from "@/siteplane/components/label";

const permissions = [
  { label: "Read", value: "read" },
  { label: "Comment", value: "comment" },
  { label: "Write", value: "write" },
];

export default function Example() {
  const labelId = useId();
  const [value, setValue] = useState<string[]>(["read", "comment"]);
  return (
    <CheckboxGroup
      allValues={permissions.map((permission) => permission.value)}
      aria-labelledby={labelId}
      onValueChange={setValue}
      value={value}
    >
      <Label id={labelId}>
        <Checkbox parent />
        Project access
      </Label>
      {permissions.map((permission) => (
        <Label className="ms-4" key={permission.value}>
          <Checkbox value={permission.value} />
          {permission.label}
        </Label>
      ))}
    </CheckboxGroup>
  );
}

Form integration

Render the Field as a Fieldset so the legend names the group and the field’s name applies to every checkbox. The form submits one entry per checked value.

Notification channels
"use client";

import { Button } from "@/siteplane/components/button";
import { Checkbox } from "@/siteplane/components/checkbox";
import { CheckboxGroup } from "@/siteplane/components/checkbox-group";
import { Field, FieldItem, FieldLabel } from "@/siteplane/components/field";
import { Fieldset, FieldsetLegend } from "@/siteplane/components/fieldset";
import { Form } from "@/siteplane/components/form";

export default function Example() {
  return (
    <Form
      className="grid w-full max-w-sm gap-4"
      onSubmit={(event) => {
        event.preventDefault();
      }}
    >
      <Field name="channels" render={(props) => <Fieldset {...props} />}>
        <FieldsetLegend>Notification channels</FieldsetLegend>
        <CheckboxGroup defaultValue={["email"]}>
          <FieldItem>
            <FieldLabel>
              <Checkbox value="email" />
              Email
            </FieldLabel>
          </FieldItem>
          <FieldItem>
            <FieldLabel>
              <Checkbox value="push" />
              Push notifications
            </FieldLabel>
          </FieldItem>
          <FieldItem>
            <FieldLabel>
              <Checkbox value="sms" />
              SMS
            </FieldLabel>
          </FieldItem>
        </CheckboxGroup>
      </Field>
      <Button type="submit">Save preferences</Button>
    </Form>
  );
}

Card style

Use Label variant="card" for options that need a description; each card toggles its own checkbox.

"use client";

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

const addOns = [
  {
    description: "Dashboards and usage reports for every project.",
    title: "Analytics",
    value: "analytics",
  },
  {
    description: "A searchable record of security events.",
    title: "Audit log",
    value: "audit-log",
  },
  {
    description: "Replies from our team within four business hours.",
    title: "Priority support",
    value: "support",
  },
];

export default function Example() {
  return (
    <CheckboxGroup
      aria-label="Add-ons"
      className="w-full max-w-sm"
      defaultValue={["analytics"]}
    >
      {addOns.map((addOn) => (
        <Label
          variant="card"
          className="flex w-full items-start"
          key={addOn.value}
        >
          <Checkbox value={addOn.value} />
          <span className="flex flex-col gap-1">
            <span>{addOn.title}</span>
            <span className="text-muted-foreground text-xs">
              {addOn.description}
            </span>
          </span>
        </Label>
      ))}
    </CheckboxGroup>
  );
}

Sizes

Set size on the group to size every checkbox; a checkbox’s own size still wins.

"use client";

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

const sizes = [
  ["sm", "small"],
  ["md", "medium"],
  ["lg", "large"],
  ["xl", "extra large"],
] as const;

export default function Example() {
  return (
    <div className="flex flex-wrap gap-8">
      {sizes.map(([size, name]) => (
        <CheckboxGroup
          aria-label={`Notification channels, ${name}`}
          defaultValue={["email"]}
          key={size}
          size={size}
        >
          <Label>
            <Checkbox value="email" />
            Email
          </Label>
          <Label>
            <Checkbox value="sms" />
            SMS
          </Label>
        </CheckboxGroup>
      ))}
    </div>
  );
}

API reference

Component properties
PropTypeDefaultDescription
CheckboxGroup.sizesm | md | lg | xlprovider / lgShared item size.
value / defaultValuestring[]uncontrolledControlled or initial selection.
onValueChange(value, eventDetails) => voidunsetSelection change callback.
allValuesstring[]unsetEvery item value; required for a parent checkbox.
disabledbooleanfalseDisables the group.

The group places its options 8 px apart. A gap-* utility in className replaces that, so a horizontal group sets its own, for example className="flex-row gap-4".

CheckboxGroupProps and CheckboxGroupPrimitive are exported. Size is the only owned prop. Checkbox is installed transitively; mark the parent checkbox with its parent prop.

Other props, refs, validation and events follow Base UI CheckboxGroup. Styled parts accept string className.

Read the installed source.

Usage notes

Space toggles each focused checkbox. Give the group and each item an accessible label.