# Checkbox

## Overview

Accessible checkbox with support for checked, unchecked, and indeterminate states. Keyboard focus styles and disabled state included.

---

## Props

### Checkbox (Root)

| Prop              | Type                         | Default     | Description                                  |
| ----------------- | ---------------------------- | ----------- | -------------------------------------------- |
| `checked`         | `boolean \| "indeterminate"` | `false`     | Current state of the checkbox.               |
| `disabled`        | `boolean`                    | `false`     | Disables interactions.                       |
| `onCheckedChange` | `(checked: boolean) => void` | `undefined` | Called when the state changes.               |
| `id`              | `string`                     | `undefined` | Useful when paired with a label's `htmlFor`. |
| `className`       | `string`                     | `""`        | Additional classes for size/layout.          |

---

## Behavior

- **Indeterminate**: Use `checked="indeterminate"` to display a dash indicator.
- **Focus & invalid**: Visual feedback for focus and invalid states is included.
- **Labeling**: Pair with `Label` and `htmlFor` for accessible labeling.

---

## Examples

### Default

```tsx
import { Checkbox } from "laif-ds";
import { Label } from "laif-ds";

export function DefaultCheckbox() {
  return (
    <div className="flex items-center gap-2">
      <Checkbox id="terms" />
      <Label htmlFor="terms">Accept terms and conditions</Label>
    </div>
  );
}
```

### Indeterminate

```tsx
import { Checkbox } from "laif-ds";
import { Label } from "laif-ds";

export function IndeterminateCheckbox() {
  return (
    <div className="flex items-center gap-2">
      <Checkbox id="partial" checked="indeterminate" />
      <Label htmlFor="partial">Partially selected options</Label>
    </div>
  );
}
```

### Disabled

```tsx
import { Checkbox } from "laif-ds";
import { Label } from "laif-ds";

export function DisabledCheckbox() {
  return (
    <div className="flex items-center gap-2">
      <Checkbox id="disabled" disabled />
      <Label htmlFor="disabled">Accept terms and conditions</Label>
    </div>
  );
}
```

### Select All Pattern

```tsx
import * as React from "react";
import { Checkbox } from "laif-ds";
import { Label } from "laif-ds";

export function SelectAllExample() {
  const [items, setItems] = React.useState([
    { id: "item1", label: "Item 1", checked: false },
    { id: "item2", label: "Item 2", checked: true },
    { id: "item3", label: "Item 3", checked: false },
  ]);

  const checkedCount = items.filter((i) => i.checked).length;
  const selectAllState =
    checkedCount === 0
      ? false
      : checkedCount === items.length
        ? true
        : ("indeterminate" as const);

  const handleSelectAll = () => {
    const newChecked = selectAllState !== true;
    setItems(items.map((i) => ({ ...i, checked: newChecked })));
  };

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2 border-b pb-2">
        <Checkbox
          id="select-all"
          checked={selectAllState}
          onCheckedChange={handleSelectAll}
        />
        <Label htmlFor="select-all">
          Select All ({checkedCount}/{items.length})
        </Label>
      </div>
      <div className="space-y-2 pl-6">
        {items.map((item) => (
          <div key={item.id} className="flex items-center gap-2">
            <Checkbox
              id={item.id}
              checked={item.checked}
              onCheckedChange={(checked) =>
                setItems(
                  items.map((i) =>
                    i.id === item.id
                      ? { ...i, checked: checked as boolean }
                      : i,
                  ),
                )
              }
            />
            <Label htmlFor={item.id}>{item.label}</Label>
          </div>
        ))}
      </div>
    </div>
  );
}
```

---

## Notes

- **Indicator**: A check icon is shown when `checked=true`, a dash for indeterminate.
- **Disabled**: Applies reduced opacity and disables pointer events.
