# Checkbox

> A native checkbox with an optional paired label. Owns the `type='checkbox'` attribute so consumers never have to set it.

- Category: form
- Status: stable (since 1.0.0)
- A11y pattern: https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/
- Tokens: --cta-background, --cta-foreground, --foreground-primary, --background-secondary
- Playground: https://design.freecodecamp.org/playground#checkbox
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `Checkbox.tsx` → `src/ui/checkbox/Checkbox.tsx` (raw: https://design.freecodecamp.org/registry/checkbox/Checkbox.tsx)
  - `checkbox.css` → `src/ui/checkbox/checkbox.css` (raw: https://design.freecodecamp.org/registry/checkbox/checkbox.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/checkbox/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/checkbox/checkbox.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

`<Checkbox>` pairs a native `<input type='checkbox'>` with an optional
inline label. When `label` is supplied the component renders a
`<label>` wrapper; otherwise it renders the bare input so callers can
associate their own label.

## Usage

```tsx
import { Checkbox } from './ui/checkbox/Checkbox';
<Checkbox name='terms' label='I agree to the terms' defaultChecked />;
```

## Keyboard

| Key   | Action                          |
| ----- | ------------------------------- |
| Space | Toggles the checked state       |
| Tab   | Moves focus to the next control |

## Accessibility

Whichever API you use, the input must have a label. The component's
wrapping `<label>` is the path of least resistance - pass `label` and the
association is guaranteed. For indeterminate state, set the DOM property
via a `ref` (React does not expose it as an attribute).

## Example

```tsx
import { Checkbox } from './ui/checkbox/Checkbox';

<Checkbox defaultChecked label="I accept the honor code" />
<Checkbox label="Email me certificate alerts" />
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | no | - |  |
| `labelClassName` | `string` | no | `` |  |

## Source: Checkbox.tsx

```tsx
import React, { forwardRef } from 'react';

export interface CheckboxProps extends Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'type'
> {
  label?: React.ReactNode;
  labelClassName?: string;
}

export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
  ({ label, labelClassName = '', className = '', id, ...rest }, ref) => {
    if (label === undefined) {
      return (
        <input
          ref={ref}
          type='checkbox'
          id={id}
          className={className}
          {...rest}
        />
      );
    }
    const classes = ['check', labelClassName].filter(Boolean).join(' ');
    return (
      <label className={classes} htmlFor={id}>
        <input
          ref={ref}
          type='checkbox'
          id={id}
          className={className}
          {...rest}
        />
        <span>{label}</span>
      </label>
    );
  }
);
Checkbox.displayName = 'Checkbox';
```

## Source: checkbox.css

```css
.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  color: var(--foreground-primary);
  cursor: pointer;
}
.check input[type='checkbox'] {
  width: 18px;
  height: 18px;
  margin-top: 3px;
  accent-color: var(--cta-background);
  cursor: inherit;
}
.check:has(input:disabled) {
  opacity: 0.5;
  cursor: not-allowed;
}
```

## HTML / vanilla variant

```html
<label class="check"><input type="checkbox" checked /> I accept the honor code</label>
<label class="check"><input type="checkbox" /> Email me certificate alerts</label>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
