Checkbox

Input for selecting one or multiple options.

import { Checkbox } from 'ui-lab-components/checkbox';
 
export function Example() {
  return <Checkbox label="Accept terms" />;
}

checkbox/01-basic-states

The default checkbox states: unchecked, checked, disabled, and disabled checked.

Loading interactive preview
import { Checkbox } from 'ui-lab-components/checkbox'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Basic States',
  description: 'The default checkbox states: unchecked, checked, disabled, and disabled checked.',
};
 
export default function Example() {
  return (
    <Flex direction="column" gap="md" style={{ width: 280 }}>
      <Checkbox id="basic-unchecked" label="Unchecked" />
      <Checkbox id="basic-checked" label="Checked" checked />
      <Checkbox id="basic-disabled" label="Disabled" disabled />
      <Checkbox id="basic-disabled-checked" label="Disabled checked" disabled checked />
    </Flex>
  );
}
 

checkbox/02-helper-text

A labeled checkbox can include supporting text and an invalid state for form feedback.

Loading interactive preview
import { Checkbox } from 'ui-lab-components/checkbox'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Helper and Error Text',
  description: 'A labeled checkbox can include supporting text and an invalid state for form feedback.',
};
 
export default function Example() {
  return (
    <Flex direction="column" gap="lg" style={{ width: 320 }}>
      <Checkbox
        id="helper-release-notes"
        label="Release notes"
        helper="Get a short product update when a new version ships."
        checked
      />
      <Checkbox
        id="helper-terms"
        label="Accept terms"
        helper="You must accept the terms before continuing."
        helperTextError
        aria-invalid="true"
      />
    </Flex>
  );
}
 
 
 

checkbox/03-controlled

Use checked and onChange when checkbox state is owned by the surrounding interface.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Button } from 'ui-lab-components/button'
import { Checkbox } from 'ui-lab-components/checkbox'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Controlled',
  description: 'Use state.checked and onChange when checkbox state is owned by the surrounding interface.',
};
 
export default function Example() {
  const [checked, setChecked] = useState(true);
 
  return (
    <Flex direction="column" gap="md" style={{ width: 300 }}>
      <Checkbox
        id="controlled-email"
        label="Email notifications"
        helper={checked ? 'Notifications are enabled.' : 'Notifications are paused.'}
        state={{ checked }}
        onChange={(event) => setChecked(event.currentTarget.checked)}
      />
      <Button variant="secondary" onClick={() => setChecked((value) => !value)}>
        {checked ? 'Turn off' : 'Turn on'}
      </Button>
    </Flex>
  );
}
 

checkbox/04-group

Use a small group when a user can select any number of related options.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Checkbox } from 'ui-lab-components/checkbox'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Checkbox Group',
  description: 'Use a small group when a user can select any number of related options.',
};
 
const subscriptionOptions = [
  'Product updates',
  'Security alerts',
  'Billing reminders',
];
 
export default function Example() {
  const [selected, setSelected] = useState<Set<string>>(
    new Set(['Product updates', 'Security alerts'])
  );
 
  const toggleOption = (option: string) => {
    setSelected((current) => {
      const next = new Set(current);
      next.has(option) ? next.delete(option) : next.add(option);
      return next;
    });
  };
 
  return (
    <Flex direction="column" gap="md" style={{ width: 300 }}>
      <div>
        <p className="text-sm font-medium text-foreground-100">Subscriptions</p>
        <p className="text-xs text-foreground-400">Choose the emails this workspace receives.</p>
      </div>
      <Flex direction="column" gap="sm">
        {subscriptionOptions.map((option) => (
          <Checkbox
            key={option}
            id={`subscription-${option.toLowerCase().replace(/ /g, '-')}`}
            label={option}
            state={{ checked: selected.has(option) }}
            onChange={() => toggleOption(option)}
          />
        ))}
      </Flex>
    </Flex>
  );
}
 

checkbox/05-indeterminate

A parent checkbox can show partial selection when only some child options are checked.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Checkbox } from 'ui-lab-components/checkbox'
import { Divider } from 'ui-lab-components/divider'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Indeterminate',
  description: 'A parent checkbox can show partial selection when only some child options are checked.',
};
 
const tableColumns = ['Name', 'Email', 'Role', 'Last active'];
 
export default function Example() {
  const [visibleColumns, setVisibleColumns] = useState<Set<string>>(
    new Set(['Name', 'Email'])
  );
 
  const allSelected = visibleColumns.size === tableColumns.length;
  const isIndeterminate = visibleColumns.size > 0 && !allSelected;
 
  const toggleAll = () => {
    setVisibleColumns(allSelected ? new Set() : new Set(tableColumns));
  };
 
  const toggleColumn = (column: string) => {
    setVisibleColumns((current) => {
      const next = new Set(current);
      next.has(column) ? next.delete(column) : next.add(column);
      return next;
    });
  };
 
  return (
    <Flex direction="column" gap="sm" style={{ width: 280 }}>
      <Checkbox
        id="columns-all"
        label="Show all columns"
        state={{ checked: allSelected, indeterminate: isIndeterminate }}
        onChange={toggleAll}
      />
      <Divider />
      <Flex direction="column" gap="sm" className="pl-8">
        {tableColumns.map((column) => (
          <Checkbox
            key={column}
            id={`column-${column.toLowerCase().replace(/ /g, '-')}`}
            label={column}
            state={{ checked: visibleColumns.has(column) }}
            onChange={() => toggleColumn(column)}
          />
        ))}
      </Flex>
    </Flex>
  );
}
 
UI Lab