Components
FormField
Composite form field providing accessible label, control, description, and error message wiring via context.
Category: Form / Composite
Import
import {
FormField,
FormFieldLabel,
FormFieldControl,
FormFieldDescription,
FormFieldMessage,
} from "@hareru/ui"Exports
| Name | Type | Description |
|---|---|---|
FormField | Component | Root container; generates a unique id and provides context |
FormFieldLabel | Component | <label> with htmlFor injected from context |
FormFieldControl | Component | Wrapper that injects id, aria-describedby, and aria-invalid into its single child |
FormFieldDescription | Component | Helper text with stable id for aria-describedby |
FormFieldMessage | Component | Error or validation message; renders as role="alert" when in error state |
Types
export interface FormFieldProps extends React.HTMLAttributes<HTMLDivElement> {
error?: boolean
}
export interface FormFieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {}
export interface FormFieldControlProps extends React.HTMLAttributes<HTMLDivElement> {}
export interface FormFieldDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}
export interface FormFieldMessageProps extends React.HTMLAttributes<HTMLParagraphElement> {}Key Props
| Prop | Type | Component | Default | Description |
|---|---|---|---|---|
error | boolean | FormField | false | Activates error styles and role="alert" on the message |
Accessibility Wiring
FormFieldControl automatically injects the following props into its direct child element:
| Injected Prop | Value | Purpose |
|---|---|---|
id | Auto-generated UUID | Associates control with label |
aria-describedby | "<id>-description <id>-message" | Links control to description and message |
aria-invalid | true (only when error=true) | Signals invalid state to screen readers |
Structure
- FormFieldLabel
[label] - FormFieldControl
[control](expected) - FormFieldDescription
[description] - FormFieldMessage
[description]
(expected) = recommended in canonical composition, not runtime-required.
Accessibility
- Notes: Automatically links label, input, and error message via aria-describedby.
Usage
import {
FormField,
FormFieldLabel,
FormFieldControl,
FormFieldDescription,
FormFieldMessage,
Input,
Button,
} from "@hareru/ui"
// Basic form field
<FormField>
<FormFieldLabel>Email</FormFieldLabel>
<FormFieldControl>
<Input type="email" placeholder="you@example.com" />
</FormFieldControl>
<FormFieldDescription>The email address used for login</FormFieldDescription>
</FormField>
// With validation error
<FormField error={!!errors.name}>
<FormFieldLabel>Name</FormFieldLabel>
<FormFieldControl>
<Input placeholder="John Doe" />
</FormFieldControl>
<FormFieldDescription>Used as your display name</FormFieldDescription>
<FormFieldMessage>Name is required</FormFieldMessage>
</FormField>
// With Textarea
<FormField error={!!errors.bio}>
<FormFieldLabel>Bio</FormFieldLabel>
<FormFieldControl>
<Textarea rows={4} placeholder="Tell us about yourself..." />
</FormFieldControl>
<FormFieldMessage>{errors.bio?.message}</FormFieldMessage>
</FormField>Notes
FormFieldControlexpects exactly one child element. Wrapping multiple elements will throw.FormFieldMessagerendersnullwhenchildrenis empty, so it is safe to always include it.FormFieldLabelandFormFieldControlmust be used within<FormField>— they will throw if the context is missing.- The
errorprop onFormFieldpropagates to bothFormFieldLabel(error style) andFormFieldMessage(role="alert").