first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
# Checkbox
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - checkbox.variants — `checkboxVariants` is the cva (…
- [checkbox.variants](./checkbox.variants.md) — `checkboxVariants` is the cva (class-variance-authority) configuration that powers every `<Checkbox>` render. It is spl…
- checkbox.variants — `checkboxVariants` is the cva (…
- [checkbox.variants](./checkbox.variants.md) — `checkboxVariants` is the cva (class-variance-authority) configuration that powers every `<Checkbox>` render. It is spl…
- checkbox.variants — `checkboxVariants` is the cva (…
- [checkbox.variants](./checkbox.variants.md) — `checkboxVariants` is the cva (class-variance-authority) configuration that powers every `<Checkbox>` render. It is spl…
- checkbox.variants — `checkboxVariants` is the cva (…
- [checkbox.variants](./checkbox.variants.md) — `checkboxVariants` is the cva (class-variance-authority) configuration that powers every `<Checkbox>` render. It is spl…
- [checkbox.variants](./checkbox.variants.md) — `checkboxVariants` is the cva (class-variance-authority) configuration that powers every `<Checkbox>` render. It is spl…
## Purpose
`<Checkbox>` is the chassis form-checkbox primitive built on `@radix-ui/react-checkbox`. Radix supplies the a11y semantics (`role="checkbox"`, `aria-checked` reflecting `true | false | "mixed"`, native `Space` activation, `disabled` propagation); the chassis layers theme-driven variant resolution, the indicator render, and the cva `size` axis so consumers can scale checkboxes inside data-table headers, settings panes, and dense forms without manual class overrides.
The indicator picks its icon based on the controlled `checked` value: `<CheckIcon>` for the boolean-true case and `<MinusIcon>` for the indeterminate case. Both icons carry a `data-icon` slot attribute so consumer themes may swap them. Refs are forwarded to the Radix Root which renders a styled `<button>`.
Icon-only checkboxes (no visible label sibling) MUST supply an `aria-label` so screen readers can announce the control. The chassis does NOT inject a fallback because the check icon's purpose is domain-specific — only the consumer knows what is being toggled.
## Features
- Three sizes (`sm`, `default`, `lg`) scaling the box and inner icon proportionally.
- Indicator render with `<CheckIcon>` for the checked state and `<MinusIcon>` for the indeterminate state — both with `data-icon` slot attribution.
- Controlled and uncontrolled use via Radix `checked` / `defaultChecked` / `onCheckedChange`.
- `aria-checked="mixed"` for the indeterminate state per WAI-ARIA spec.
- `disabled` blocks pointer + keyboard input and decays opacity.
- `data-state="checked|unchecked|indeterminate"` mirrored on the rendered button so consumer cva configs / CSS can react.
- Refs forwarded to the Radix Root.
- `motion-reduce:transition-none` collapses transitions for `prefers-reduced-motion: reduce`.
## Usage: Basic Example
```tsx
import { Checkbox } from "@suaveplan/react-ui";
export function AcceptTerms() {
return (
<div className="flex items-center gap-2">
<Checkbox id="terms" />
<label htmlFor="terms">Accept terms</label>
</div>
);
}
```
## Usage: Advanced Example
```tsx
import { Checkbox } from "@suaveplan/react-ui";
import { useMemo, useState } from "react";
interface Permission {
readonly id: string;
readonly label: string;
}
export function PermissionMatrix({ items }: { items: readonly Permission[] }) {
const [selected, setSelected] = useState<readonly string[]>([]);
const allChecked = selected.length === items.length;
const someChecked = selected.length > 0 && !allChecked;
const headerState = allChecked ? true : someChecked ? "indeterminate" : false;
const toggleAll = () =>
setSelected(allChecked ? [] : items.map((i) => i.id));
const toggleOne = (id: string) =>
setSelected((prev) =>
prev.includes(id) ? prev.filter((p) => p !== id) : [...prev, id]
);
return (
<table>
<thead>
<tr>
<th>
<Checkbox
aria-label="select all"
checked={headerState}
onCheckedChange={toggleAll}
/>
</th>
<th>Permission</th>
</tr>
</thead>
<tbody>
{items.map((item) => (
<tr key={item.id}>
<td>
<Checkbox
aria-label={`select ${item.label}`}
checked={selected.includes(item.id)}
onCheckedChange={() => toggleOne(item.id)}
/>
</td>
<td>{item.label}</td>
</tr>
))}
</tbody>
</table>
);
}
```
## API Reference
### `<Checkbox>`
`forwardRef<ComponentRef<typeof CheckboxPrimitive.Root>, CheckboxProps>` — wraps Radix Root, renders a `<button role="checkbox">` containing the Radix Indicator with the appropriate icon.
#### `CheckboxProps`
Inherits every prop from Radix `CheckboxPrimitive.Root` except `asChild`. Adds:
| Prop | Type | Default | Description |
|---|---|---|---|
| `size` | `"sm" \| "default" \| "lg"` | `"default"` | Visual variant scaling box + icon. |
Common Radix props consumers will use:
| Prop | Type | Default | Description |
|---|---|---|---|
| `checked` | `boolean \| "indeterminate"` | _uncontrolled_ | Controlled state. |
| `defaultChecked` | `boolean` | `false` | Initial state for uncontrolled use. |
| `onCheckedChange` | `(checked: boolean \| "indeterminate") => void` | _none_ | Fires on state change. |
| `disabled` | `boolean` | `false` | Blocks input + decays opacity. |
| `required` | `boolean` | `false` | Native form-field `required`. |
| `name` | `string` | _none_ | Native form-field name. |
| `value` | `string` | `"on"` | Native form-field value when checked. |
#### `checkboxVariants`
The bare cva resolver. Exported so external consumers can re-use the variants directly.
## Implementation Notes
- The variants module is intentionally separate (`checkbox.variants.ts`) so an ejected source copy keeps the cva config in a dedicated file.
- The indicator uses `<CheckIcon>` / `<MinusIcon>` from `lucide-react` rather than inline SVG so consumers replacing the icon library via `ThemePlugin.iconLibrary` get a coherent swap surface.
- The chassis does NOT auto-inject an `aria-label` for icon-only use — see `Purpose` for the rationale.
- The `data-state` attribute is supplied by Radix; the chassis cva config keys `data-[state=checked]:bg-primary` / `data-[state=indeterminate]:bg-primary` off it so checked + indeterminate render with the same primary background.
- Refs target the Radix Root (the `<button>` element) — consumers can `.focus()` the checkbox programmatically through the forwarded ref.