6.5 KiB
Field
(no submodules)
- field.variants — `fieldVariants`, `fieldLabelVarian…-
field.variants —
fieldVariants,fieldLabelVariants,fieldDescriptionVariants, andfieldErrorVariantsare the four cva (class-var… -
field.variants —
fieldVariants, `fieldLabelVarian… -
field.variants —
fieldVariants,fieldLabelVariants,fieldDescriptionVariants, andfieldErrorVariantsare the four cva (class-var… -
field.variants —
fieldVariants, `fieldLabelVarian… -
field.variants —
fieldVariants,fieldLabelVariants,fieldDescriptionVariants, andfieldErrorVariantsare the four cva (class-var… -
field.variants —
fieldVariants, `fieldLabelVarian… -
field.variants —
fieldVariants,fieldLabelVariants,fieldDescriptionVariants, andfieldErrorVariantsare the four cva (class-var… -
field.variants —
fieldVariants,fieldLabelVariants,fieldDescriptionVariants, andfieldErrorVariantsare 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 withflex flex-col gap-2layout (NOTspace-y-*per shadcn skill rule).<FieldLabel>built on@radix-ui/react-labelso clicking the label focuses the matched input.<FieldDescription>renders a muted<p>for helper text — typically wired to the control viaaria-describedby.<FieldError>renders a destructive<p role="alert">so screen readers announce the message immediately when it appears.data-invalidon<Field>automatically flips descendant<FieldLabel>colour to destructive.data-disabledon<Field>decays opacity.- Refs forwarded on every primitive.
- Theme-driven variant overrides via
useThemedVariants("Field" | "FieldLabel" | "FieldDescription" | "FieldError").
Usage: Basic Example
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
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/fieldnamed-group selector lets<FieldLabel>flip its colour without needing a sibling<FieldError>to be present. <FieldError>defaults torole="alert"(assertive announcement) so screen readers announce validation errors immediately when they appear. Consumers that want a polite announcement override withrole="status".- Per the cross-cutting reconciliation note (#1), shadcn ships
fieldandfield-groupas separate registry items; this chassis mirrors that split so the primitives evolve independently and can be ejected piecemeal.