import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

export function CheckboxBasicDemo() {
  const [checked, setChecked] = useState(false);
  return (
    <Checkbox
      label="Accept terms and conditions"
      checked={checked}
      onCheckedChange={setChecked}
    />
  );
}

Installation

Barrel

import { Checkbox } from "@cloudflare/kumo";

Granular

import { Checkbox } from "@cloudflare/kumo/components/checkbox";

Usage

import { Checkbox } from "@cloudflare/kumo";

export default function Example() {
  return <Checkbox label="Accept terms" />;
}

Examples

Default

Checkbox with built-in label. The label automatically displays in a horizontal layout (checkbox before label).

import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

export function CheckboxDefaultDemo() {
  const [checked, setChecked] = useState(false);
  return (
    <Checkbox
      label="Enable notifications"
      checked={checked}
      onCheckedChange={setChecked}
    />
  );
}

Checked

import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

export function CheckboxCheckedDemo() {
  const [checked, setChecked] = useState(true);
  return (
    <Checkbox label="I agree" checked={checked} onCheckedChange={setChecked} />
  );
}

Indeterminate

Used for “select all” patterns when some but not all items are selected.

import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

export function CheckboxIndeterminateDemo() {
  const [indeterminate, setIndeterminate] = useState(true);
  return (
    <Checkbox
      label="Select all"
      indeterminate={indeterminate}
      onCheckedChange={setIndeterminate}
    />
  );
}

Label First Layout

Use controlFirst={false} to place the label before the checkbox.

import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

export function CheckboxLabelFirstDemo() {
  const [checked, setChecked] = useState(false);
  return (
    <Checkbox
      label="Remember me"
      controlFirst={false}
      checked={checked}
      onCheckedChange={setChecked}
    />
  );
}

Disabled

import { Checkbox } from "@cloudflare/kumo";

export function CheckboxDisabledDemo() {
  return <Checkbox label="Disabled option" disabled />;
}

Error

Error variant provides visual styling (red ring). For error messages, use Checkbox.Group.

import { Checkbox } from "@cloudflare/kumo";

export function CheckboxErrorDemo() {
  return <Checkbox label="Invalid option" variant="error" />;
}

Checkbox Group

Group multiple checkboxes with a legend, description, and shared error messages. Uses Checkbox.Group and Checkbox.Item.

Email preferences

Choose how you'd like to receive updates

import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

export function CheckboxGroupDemo() {
  const [preferences, setPreferences] = useState<string[]>(["email"]);

  return (
    <Checkbox.Group
      legend="Email preferences"
      description="Choose how you'd like to receive updates"
      value={preferences}
      onValueChange={setPreferences}
    >
      <Checkbox.Item value="email" label="Email notifications" />
      <Checkbox.Item value="sms" label="SMS notifications" />
      <Checkbox.Item value="push" label="Push notifications" />
    </Checkbox.Group>
  );
}

Bordered Checkbox Group

Use appearance="bordered" to place checkbox options in one contiguous surface with shared dividers. Set orientation="horizontal" for a side-by-side layout; groups are vertical by default. Bordered groups place controls at the end unless controlFirst is set. The examples below also cover long wrapping text, disabled options, and larger option sets.

Notifications
Alert categories (control first)
Export contents

Long labels should wrap without moving or shrinking the controls.

Team permissions
import { useState } from "react";
import { Badge, Checkbox } from "@cloudflare/kumo";
import { ChatCircleTextIcon, EnvelopeIcon } from "@phosphor-icons/react";

export function CheckboxBorderedGroupDemo() {
  const [notifications, setNotifications] = useState<string[]>(["email"]);
  const [alertCategories, setAlertCategories] = useState<string[]>([
    "security",
    "performance",
  ]);
  const [exportContents, setExportContents] = useState<string[]>([
    "configuration",
    "analytics",
  ]);
  const [permissions, setPermissions] = useState<string[]>(["read", "edit"]);

  return (
    <div className="flex flex-col gap-8">
      <Checkbox.Group
        legend="Notifications"
        appearance="bordered"
        orientation="horizontal"
        value={notifications}
        onValueChange={setNotifications}
      >
        <Checkbox.Item
          value="email"
          label={
            <span className="flex items-center gap-2">
              <EnvelopeIcon
                size={18}
                className="text-kumo-subtle"
                aria-hidden
              />
              Email
            </span>
          }
        />
        <Checkbox.Item
          value="sms"
          label={
            <span className="flex items-center gap-2">
              <ChatCircleTextIcon
                size={18}
                className="text-kumo-subtle"
                aria-hidden
              />
              SMS
            </span>
          }
        />
      </Checkbox.Group>
      <Checkbox.Group
        legend="Alert categories (control first)"
        appearance="bordered"
        controlFirst
        value={alertCategories}
        onValueChange={setAlertCategories}
      >
        <Checkbox.Item value="security" label="Security" />
        <Checkbox.Item value="performance" label="Performance" />
        <Checkbox.Item
          value="reliability"
          label={
            <span className="flex flex-wrap items-center gap-2">
              Reliability
              <Badge variant="neutral">Beta</Badge>
            </span>
          }
        />
        <Checkbox.Item value="billing" label="Billing (unavailable)" disabled />
      </Checkbox.Group>
      <Checkbox.Group
        legend="Export contents"
        description="Long labels should wrap without moving or shrinking the controls."
        appearance="bordered"
        orientation="horizontal"
        value={exportContents}
        onValueChange={setExportContents}
      >
        <Checkbox.Item
          value="configuration"
          label="Account and zone configuration settings"
        />
        <Checkbox.Item
          value="analytics"
          label="Historical analytics and event data"
        />
        <Checkbox.Item
          value="members"
          label="Member profiles, roles, and access policies"
        />
      </Checkbox.Group>
      <Checkbox.Group
        legend="Team permissions"
        appearance="bordered"
        controlFirst
        value={permissions}
        onValueChange={setPermissions}
      >
        <Checkbox.Item value="read" label="View resources" />
        <Checkbox.Item value="edit" label="Create and edit resources" />
        <Checkbox.Item value="deploy" label="Deploy to production" />
        <Checkbox.Item value="members" label="Manage team members" />
        <Checkbox.Item value="billing" label="Manage billing" disabled />
      </Checkbox.Group>
    </div>
  );
}

Checkbox Group with Error

Show validation errors at the group level. Error replaces description when present.

Required preferences

Please select at least one notification method

import { Checkbox } from "@cloudflare/kumo";

export function CheckboxGroupErrorDemo() {
  return (
    <Checkbox.Group
      legend="Required preferences"
      error="Please select at least one notification method"
      value={[]}
      onValueChange={() => {}}
    >
      <Checkbox.Item value="email" label="Email" variant="error" />
      <Checkbox.Item value="sms" label="SMS" variant="error" />
    </Checkbox.Group>
  );
}

Visually Hidden Legend

Use Checkbox.Legend with className="sr-only" to keep the legend accessible to screen readers while hiding it visually. This is useful when the group is already labeled by a parent Field or heading, and showing the legend would create a redundant label.

Notification preferences
import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

/** Shows Checkbox.Legend with sr-only to visually hide the legend while keeping it accessible, useful when a parent Field already provides a visible label */
export function CheckboxLegendSrOnlyDemo() {
  const [preferences, setPreferences] = useState<string[]>(["email"]);
  return (
    <Checkbox.Group value={preferences} onValueChange={setPreferences}>
      <Checkbox.Legend className="sr-only">
        Notification preferences
      </Checkbox.Legend>
      <Checkbox.Item value="email" label="Email notifications" />
      <Checkbox.Item value="sms" label="SMS notifications" />
      <Checkbox.Item value="push" label="Push notifications" />
    </Checkbox.Group>
  );
}

Custom Legend Styling

Checkbox.Legend accepts className for full control over legend presentation. Use it instead of the legend string prop when you need custom typography, colors, or layout.

Notification preferences
import { useState } from "react";
import { Checkbox } from "@cloudflare/kumo";

/** Shows Checkbox.Legend with custom styling for full control over legend presentation */
export function CheckboxLegendCustomDemo() {
  const [preferences, setPreferences] = useState<string[]>(["email"]);
  return (
    <Checkbox.Group value={preferences} onValueChange={setPreferences}>
      <Checkbox.Legend className="text-sm font-normal text-kumo-subtle">
        Notification preferences
      </Checkbox.Legend>
      <Checkbox.Item value="email" label="Email notifications" />
      <Checkbox.Item value="sms" label="SMS notifications" />
      <Checkbox.Item value="push" label="Push notifications" />
    </Checkbox.Group>
  );
}

API Reference

Checkbox

Single checkbox component with built-in label and horizontal layout.

PropTypeDefaultDescription
variant"default" | "error""default"Visual variant: "default" or "error" for validation failures (visual only, no error text)
labelReactNode-Label content for the checkbox (enables built-in Field wrapper) - can be a string or any React node
labelTooltipReactNode-Tooltip content to display next to the label via an info icon
controlFirstboolean-When true (default), checkbox appears before label. When false, label appears before checkbox.
checkedboolean-Whether the checkbox is checked (controlled)
indeterminateboolean-Whether the checkbox is in indeterminate state
disabledboolean-Whether the checkbox is disabled
namestring-Name for form submission
requiredboolean-Whether the field is required
classNamestring-Additional class name

Checkbox.Group

Wrapper for multiple checkboxes with legend, description, and error support.

PropTypeDefaultDescription
legendstring-Legend text for the group. For more control over legend styling, omit this prop and use `<Checkbox.Legend>` as a child instead.
children*ReactNode-Child Checkbox.Item components (and optionally a Checkbox.Legend)
errorstring-Error message for the group (only appears in groups, not single checkboxes)
descriptionReactNode-Helper text for the group
valuestring[]-Values of checkboxes that should be checked (controlled)
allValuesstring[]-All possible checkbox values (required for parent checkbox pattern)
disabledboolean-Whether all checkboxes in the group are disabled
orientationCheckboxGroupOrientation-Layout direction of the checkbox items.
appearanceCheckboxGroupAppearance-Visual treatment applied to the group.
controlFirstboolean-When true, checkbox appears before label. When false, label appears before checkbox. Defaults to true for default appearance and false for bordered appearance.
classNamestring-Additional CSS classes

Checkbox.Legend

Composable legend sub-component for Checkbox.Group. Accepts className for full styling control (e.g. className="sr-only" to visually hide). Use instead of the legend string prop when you need custom legend styling.

PropTypeDefaultDescription
children*ReactNode-Legend content
classNamestring-Additional CSS classes (e.g. "sr-only" to visually hide the legend)

Checkbox.Item

Individual checkbox within Checkbox.Group.

PropTypeDefault

No component-specific props. Accepts standard HTML attributes.

Accessibility

Label Requirement

Single checkboxes require a label prop or aria-label for accessibility. Missing labels trigger console warnings in development.

Keyboard Navigation

Space toggles the checkbox. Tab moves focus between checkboxes.

Screen Readers

Checkbox.Group uses semantic <fieldset> and <legend> elements for proper grouping announcement.