first commit
This commit is contained in:
148
docs/ui/react/react-ui/src/components/checkbox/checkbox.md
Normal file
148
docs/ui/react/react-ui/src/components/checkbox/checkbox.md
Normal 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.
|
||||
Reference in New Issue
Block a user