Forms
Form Field
Form Field is a shared field wrapper for label, description, required indicator, and validation placement — not a visual input.
Figma naming reference: Form Field Wrapper. React implementation: FormField.
State (Default/Error) — composition wrapper
stableReact AvailableFigma AvailableDocs Partial
- React last updated
- 2026-07-13
- Documentation last updated
- 2026-06-01
- Accessibility target
- WCAG 2.2 AA (target)
- Version
- 1.0.0
Known open questions
- Horizontal label layout is unresolved in Figma — vertical layout only.
- React name is FormField; Figma name is Form Field Wrapper.
Purpose
Shared field chrome for label, description, required indicator, and validation output — wrapping any form control without duplicating field logic per control.
Anatomy
FormField = label + control slot + supporting text or ValidationMessage. The nested control owns its own input semantics.
Variants and states
default · error
When to use
Advanced composition: one label, helper or error shared by a custom or grouped control that has no complete field component of its own, such as a checkbox list under one heading or a native control you supply through the render prop. Complete field components such as Text Input already compose Form Field internally — use them for ordinary single controls and do not wrap them in Form Field.
When not to use
Wrapping Text Input (or any other complete field component): it already renders its own label, supporting text and error, so the wrapper would duplicate the label. Standalone Checkbox, Radio, or Switch instances that already include an inline label. Do not treat Form Field as a visual input.
Accessibility
Associates label text with the nested control through htmlFor/id or fieldset/legend patterns. Validation messages must be linked with aria-describedby.
Keyboard behavior
FormField does not introduce keyboard behavior — focus moves to the nested control using native tab order.
Common mistakes
Wrapping a complete field component such as Text Input in Form Field, which duplicates the label and error wiring. Rendering a separate Validation Message for an error that Form Field already renders. Using Form Field as if it were a text input.
Properties
Label (text). Required (boolean). Helper Text (text). Control supplied as child render function.
Tokens used
semantic/text/primarysemantic/text/secondarysemantic/text/danger
Known limitation
Form Field renders its `error` through Validation Message with announce="off": the error reaches assistive technology through aria-invalid and aria-describedby on the control, not through a live region. The `children` prop is a render function, not a React node.
Component API
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | — | Visible or visually hidden field label. |
| controlId | string | — | Stable id passed to the nested control. |
| required | boolean | false | Shows required indicator. |
| supportingText | string | — | Helper/description linked with aria-describedby. |
| error | string | — | Static validation message rendered through ValidationMessage. |
| children | (args) => ReactNode | — | Render prop receiving controlId, describedBy, invalid. |
React example
Copy React example
import { TextInput } from "@/components/ui/TextInput";
export function Example() {
return (
<TextInput
label="Workspace name"
supportingText="Visible to your team."
placeholder="Acme Design"
/>
);
}