Field
Wrapper for form inputs with label, description, and error message.
When to Use
Use Field when you need to:
- Wrap a form control with a label, description, and error message
- Build consistent form layouts with vertical or horizontal orientation
- Group related fields with a fieldset and legend for semantic structure
- Display validation errors alongside form controls
- Create accessible checkbox, radio, or switch layouts with proper labelling
When Not to Use
- Standalone labels without a control - use Label directly
- Complex multi-step forms with validation - consider Form with React Hook Form
- A single input without any description or error handling - a plain Input may suffice
- Server-side form validation with TanStack - use TanStack Form
Default
A complete profile form with fieldset, legend, and descriptions.
Input Fields
Basic input fields with labels and descriptions. Description can appear above or below the control.
Textarea
Textarea field with label and helper text for longer-form content.
Select
Select field with label and description for dropdown selection.
Select your department or area of work.
Checkbox Group
Horizontal checkbox fields with labels. Uses orientation='horizontal' for side-by-side layout.
Radio Group
Radio group with subscription plan options inside a fieldset.
Switch
Horizontal switch with label and description using FieldContent for rich labelling.
Enable multi-factor authentication for your account. If you do not have a two-factor device, you can use a one-time code sent to your email.
Validation Errors
Fields with error states using data-invalid and FieldError with role='alert'.
UX & Design Guidelines
Layout & Orientation
Use orientation="vertical" (default) for text inputs, textareas, and selects where the label sits above the control. Use orientation="horizontal" for checkboxes, radios, and switches where label and control sit side-by-side. Use orientation="responsive" to auto-switch between vertical on narrow containers and horizontal on wider ones.
Grouping & Structure
Wrap related fields in a FieldSet with a FieldLegend to create semantic groups. Use FieldGroup to stack multiple fields with consistent gap-7 spacing. Nest FieldGroup components for sub-sections with tighter gap-4 spacing.
Error Handling
Add data-invalid to the Field wrapper to activate error styling. Always pair with aria-invalid on the form control and a FieldError message. Multiple errors are automatically rendered as a bulleted list via the errors prop.
Color & Tokens
Labels use text-foreground for primary readability. Descriptions use text-muted-foreground for secondary emphasis. Error states apply text-destructive automatically via data-[invalid=true]. Disabled fields reduce opacity to 50% through group-data-[disabled=true]/field:opacity-50.
Accessibility
Keyboard Navigation
- Tab -- Move focus between form controls within the field
- Space -- Toggle checkboxes and switches
- Arrow Up / Arrow Down -- Navigate between radio options in a group
- Enter -- Submit the form when focused on any control
Screen Reader Support
FieldLabeluses thehtmlForattribute to associate labels with controlsFieldErrorusesrole="alert"so errors are announced immediatelyFieldoutputsrole="group"to group label, control, and descriptionFieldSetandFieldLegendprovide native fieldset/legend semantics for assistive tech
Error Announcements
When data-invalid is set, FieldError renders with role="alert", which triggers an immediate announcement by screen readers. Always add aria-invalid on the input and connect via aria-describedby for full association.
Focus Management
Labels with htmlFor clicking the label focuses the associated control. Disabled fields apply opacity-50 and prevent interaction. Focus indicators follow the design system ring styles for consistent visual feedback.
ARIA Attributes
{/* Field with label association */}
<Field>
<FieldLabel htmlFor="name">Full Name</FieldLabel>
<Input id="name" placeholder="Enter your name" />
<FieldDescription>Your legal name as it appears on documents.</FieldDescription>
</Field>
{/* Field with error state - uses role="alert" */}
<Field data-invalid>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" aria-invalid aria-describedby="email-error" />
<FieldError id="email-error">Enter a valid email address.</FieldError>
</Field>
{/* FieldSet groups related controls with legend */}
<FieldSet>
<FieldLegend>Notification Preferences</FieldLegend>
<FieldGroup>
<Field orientation="horizontal">
<Checkbox id="email-notify" />
<FieldLabel htmlFor="email-notify">Email notifications</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
{/* Switch with FieldContent for accessible description */}
<Field orientation="horizontal">
<FieldContent>
<FieldLabel htmlFor="dark-mode">Dark Mode</FieldLabel>
<FieldDescription>Toggle between light and dark themes.</FieldDescription>
</FieldContent>
<Switch id="dark-mode" />
</Field>Related Components
API Reference
The Field system is composed of multiple sub-components, each accepting standard HTML attributes in addition to the props listed below.
Field
Core wrapper for a single form control with label, description, and error.
| Prop | Type | Default | Description |
|---|---|---|---|
| orientation | "vertical" | "horizontal" | "responsive" | "vertical" | Layout orientation for the field. Vertical stacks label above control; horizontal places them side-by-side. |
| data-invalid | boolean | --- | When present, applies error state styling with text-destructive. |
| className | string | --- | Additional CSS classes to apply to the field wrapper. |
FieldSet
Semantic fieldset container for grouping related fields.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | --- | Additional CSS classes to apply to the fieldset container. |
FieldGroup
Layout wrapper for stacking Field components with consistent spacing.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | --- | Additional CSS classes to apply to the group wrapper. |
FieldLegend
Legend element for FieldSet with variant options for visual sizing.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "legend" | "label" | "legend" | Visual style variant. "legend" uses base text size; "label" uses smaller text. |
| className | string | --- | Additional CSS classes to apply to the legend. |
FieldLabel
Accessible label built on the Label primitive for form controls.
| Prop | Type | Default | Description |
|---|---|---|---|
| htmlFor | string | --- | Associates the label with a form control via its id attribute. |
| asChild | boolean | false | When true, renders its child as the root element, merging props and behavior. |
| className | string | --- | Additional CSS classes to apply to the label. |
FieldDescription
Helper text slot for additional context below or above a control.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | --- | Additional CSS classes to apply to the description text. |
FieldError
Error message display with role="alert" for immediate screen reader announcements.
| Prop | Type | Default | Description |
|---|---|---|---|
| errors | Array<{ message?: string }> | --- | Array of error objects from form validation. Renders a single message or a bulleted list for multiple. |
| className | string | --- | Additional CSS classes to apply to the error container. |
FieldContent
Flex container for grouping label and description in horizontal layouts.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | --- | Additional CSS classes to apply to the content wrapper. |
FieldSeparator
Visual separator between fields with optional centered text content.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | --- | Optional text content displayed centered on the separator line. |
| className | string | --- | Additional CSS classes to apply to the separator. |