Initial Commit
This commit is contained in:
141
packages/ui/react/react-ui/src/components/field/field.md
Normal file
141
packages/ui/react/react-ui/src/components/field/field.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# Field
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs --> - field.variants — `fieldVariants`, `fieldLabelVarian…
|
||||
- [field.variants](./field.variants.md) — `fieldVariants`, `fieldLabelVariants`, `fieldDescriptionVariants`, and `fieldErrorVariants` are the four cva (class-var…
|
||||
- field.variants — `fieldVariants`, `fieldLabelVarian…
|
||||
|
||||
- [field.variants](./field.variants.md) — `fieldVariants`, `fieldLabelVariants`, `fieldDescriptionVariants`, and `fieldErrorVariants` are the four cva (class-var…
|
||||
|
||||
- field.variants — `fieldVariants`, `fieldLabelVarian…
|
||||
|
||||
- [field.variants](./field.variants.md) — `fieldVariants`, `fieldLabelVariants`, `fieldDescriptionVariants`, and `fieldErrorVariants` are the four cva (class-var…
|
||||
|
||||
- field.variants — `fieldVariants`, `fieldLabelVarian…
|
||||
|
||||
- [field.variants](./field.variants.md) — `fieldVariants`, `fieldLabelVariants`, `fieldDescriptionVariants`, and `fieldErrorVariants` are the four cva (class-var…
|
||||
- [field.variants](./field.variants.md) — `fieldVariants`, `fieldLabelVariants`, `fieldDescriptionVariants`, and `fieldErrorVariants` are the four cva (class-var…
|
||||
|
||||
## Purpose
|
||||
|
||||
`<Field>` is the chassis form-field container — a semantic wrapper around a single form control plus its label, description, and error message. It carries the `data-invalid` and `data-disabled` selectors so descendant `<FieldLabel>` instances pick up the destructive text colour and opacity decay automatically through the cva `group-data-[invalid=true]/field:` selector.
|
||||
|
||||
The four primitives in this module — `<Field>`, `<FieldLabel>`, `<FieldDescription>`, `<FieldError>` — compose into a complete form-field surface. Per the cross-cutting reconciliation note (#1) shadcn ships `field` as a separate registry item from `field-group`; this package mirrors that split so each primitive evolves independently.
|
||||
|
||||
`<Field>` does NOT auto-detect child invalid/disabled state — consumers pass the booleans explicitly. This keeps the chassis a pure styling primitive: the form library (sibling change `enterprise-react-forms-v2`) owns the validation orchestration and forwards `invalid` / `disabled` based on its own state.
|
||||
|
||||
## Features
|
||||
|
||||
- `<Field>` container with `flex flex-col gap-2` layout (NOT `space-y-*` per shadcn skill rule).
|
||||
- `<FieldLabel>` built on `@radix-ui/react-label` so clicking the label focuses the matched input.
|
||||
- `<FieldDescription>` renders a muted `<p>` for helper text — typically wired to the control via `aria-describedby`.
|
||||
- `<FieldError>` renders a destructive `<p role="alert">` so screen readers announce the message immediately when it appears.
|
||||
- `data-invalid` on `<Field>` automatically flips descendant `<FieldLabel>` colour to destructive.
|
||||
- `data-disabled` on `<Field>` decays opacity.
|
||||
- Refs forwarded on every primitive.
|
||||
- Theme-driven variant overrides via `useThemedVariants("Field" | "FieldLabel" | "FieldDescription" | "FieldError")`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```tsx
|
||||
import { Field, FieldLabel, Input } from "@suaveplan/react-ui";
|
||||
|
||||
export function NameField() {
|
||||
return (
|
||||
<Field>
|
||||
<FieldLabel htmlFor="name">Name</FieldLabel>
|
||||
<Input id="name" />
|
||||
</Field>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```tsx
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
FieldError,
|
||||
FieldLabel,
|
||||
Input,
|
||||
} from "@suaveplan/react-ui";
|
||||
import { useState } from "react";
|
||||
|
||||
export function PasswordField() {
|
||||
const [pwd, setPwd] = useState("");
|
||||
const tooShort = pwd.length > 0 && pwd.length < 8;
|
||||
|
||||
return (
|
||||
<Field invalid={tooShort}>
|
||||
<FieldLabel htmlFor="pwd">Password</FieldLabel>
|
||||
<Input
|
||||
id="pwd"
|
||||
type="password"
|
||||
value={pwd}
|
||||
invalid={tooShort}
|
||||
aria-invalid={tooShort}
|
||||
aria-describedby="pwd-help pwd-err"
|
||||
onChange={(e) => setPwd(e.currentTarget.value)}
|
||||
/>
|
||||
<FieldDescription id="pwd-help">
|
||||
At least 8 characters.
|
||||
</FieldDescription>
|
||||
{tooShort ? (
|
||||
<FieldError id="pwd-err">Too short.</FieldError>
|
||||
) : null}
|
||||
</Field>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `<Field>`
|
||||
|
||||
`forwardRef<HTMLDivElement, FieldProps>` — renders a `<div>` container.
|
||||
|
||||
#### `FieldProps`
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `invalid` | `boolean` | `false` | Drives `data-invalid="true"` on the container. |
|
||||
| `disabled` | `boolean` | `false` | Drives `data-disabled="true"` on the container. |
|
||||
| _all native_ `HTMLAttributes<HTMLDivElement>` | _native_ | _native_ | Forwarded as-is. |
|
||||
|
||||
### `<FieldLabel>`
|
||||
|
||||
`forwardRef<ComponentRef<typeof LabelPrimitive.Root>, FieldLabelProps>` — wraps `@radix-ui/react-label` with the chassis cva applied.
|
||||
|
||||
#### `FieldLabelProps`
|
||||
|
||||
Inherits every prop from `LabelPrimitive.Root` — `htmlFor`, `children`, native HTML attributes.
|
||||
|
||||
### `<FieldDescription>`
|
||||
|
||||
`forwardRef<HTMLParagraphElement, FieldDescriptionProps>` — renders a `<p>` with muted text.
|
||||
|
||||
#### `FieldDescriptionProps`
|
||||
|
||||
Inherits every prop from `HTMLAttributes<HTMLParagraphElement>`.
|
||||
|
||||
### `<FieldError>`
|
||||
|
||||
`forwardRef<HTMLParagraphElement, FieldErrorProps>` — renders a `<p>` with destructive colour and `role="alert"` by default.
|
||||
|
||||
#### `FieldErrorProps`
|
||||
|
||||
Inherits every prop from `HTMLAttributes<HTMLParagraphElement>`. The default `role="alert"` can be overridden by passing `role="status"` (for non-blocking errors).
|
||||
|
||||
#### Cva resolvers
|
||||
|
||||
`fieldVariants`, `fieldLabelVariants`, `fieldDescriptionVariants`, `fieldErrorVariants` are all exported as bare cva resolvers for external composition.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The four primitives are co-located in a single component module because they always compose together; splitting them into four directories would create import-tax for no benefit.
|
||||
- `<Field>` does NOT walk children to detect invalid/disabled state — consumers pass the booleans explicitly. This keeps the chassis a pure styling primitive.
|
||||
- The cva `group/field` named-group selector lets `<FieldLabel>` flip its colour without needing a sibling `<FieldError>` to be present.
|
||||
- `<FieldError>` defaults to `role="alert"` (assertive announcement) so screen readers announce validation errors immediately when they appear. Consumers that want a polite announcement override with `role="status"`.
|
||||
- Per the cross-cutting reconciliation note (#1), shadcn ships `field` and `field-group` as separate registry items; this chassis mirrors that split so the primitives evolve independently and can be ejected piecemeal.
|
||||
Reference in New Issue
Block a user