View fulldotdev/ui on GitHub

Field

Combine labels, controls, and help text to compose accessible form fields and grouped inputs.

Installation

npx shadcn@latest add @fulldev/field

Usage

import {
  Field,
  FieldContent,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSeparator,
  FieldSet,
  FieldTitle,
} from "@/components/ui/field"
<FieldSet>
  <FieldLegend>Profile</FieldLegend>
  <FieldGroup>
    <Field>
      <FieldLabel for="name">Full name</FieldLabel>
      <Input id="name" autocomplete="off" placeholder="Evil Rabbit" />
      <FieldDescription>This appears on invoices and emails.</FieldDescription>
    </Field>
    <Field>
      <FieldLabel for="username">Username</FieldLabel>
      <Input id="username" autocomplete="off" aria-invalid="true" />
      <FieldError>Choose another username.</FieldError>
    </Field>
    <Field orientation="horizontal">
      <Switch id="newsletter" />
      <FieldLabel for="newsletter">Subscribe to the newsletter</FieldLabel>
    </Field>
  </FieldGroup>
</FieldSet>

Composition

FieldSet
├── FieldLegend
├── FieldDescription
└── FieldGroup
    ├── Field
    │   ├── FieldLabel
    │   ├── Input / Textarea / Switch / Select
    │   ├── FieldDescription
    │   └── FieldError
    ├── FieldSeparator
    └── Field
        ├── FieldLabel
        └── Input / Textarea / Switch / Select
  • Field is the core wrapper for a single field.
  • FieldContent is a flex column that groups label and description. Not required if you have no description.
  • Wrap related fields with FieldGroup, and use FieldSet with FieldLegend for semantic grouping.

Input

Textarea

Select

Slider

Fieldset

Checkbox

Radio

Switch

Choice Card

Wrap Field components inside FieldLabel to create selectable field groups. This works with RadioGroupItem, Checkbox and Switch components.

Field Group

Stack Field components with FieldGroup. Add FieldSeparator to divide them.

RTL

Responsive Layout

  • Vertical fields: the default orientation stacks label, control, and helper text, ideal for mobile-first layouts.
  • Horizontal fields: set orientation="horizontal" on Field to align the label and control side by side. Pair with FieldContent to keep descriptions aligned.
  • Responsive fields: set orientation="responsive" to switch from a column to a row when the parent FieldGroup is at least @md wide. FieldGroup is already a @container/field-group.

Validation and Errors

  • Add data-invalid="true" to Field to switch the entire block into an error state.
  • Add aria-invalid="true" on the input itself for assistive technologies.
  • Render FieldError immediately after the control or inside FieldContent to keep error messages aligned with the field.
<Field data-invalid="true">
  <FieldLabel for="email">Email</FieldLabel>
  <Input id="email" type="email" aria-invalid="true" />
  <FieldError>Enter a valid email address.</FieldError>
</Field>

Accessibility

  • FieldSet and FieldLegend keep related controls grouped for keyboard and assistive tech users.
  • Field outputs role="group" so nested controls inherit labeling from FieldLabel and FieldLegend when combined.
  • FieldError renders with role="alert", and only when it has content.
  • Apply FieldSeparator sparingly to ensure screen readers encounter clear section boundaries.

API Reference

Source: src/components/ui/field

All parts accept class and the attributes of the element they render.

ComponentPropTypeDefault
Fieldorientation"vertical" | "horizontal" | "responsive""vertical"
FieldLegendvariant"legend" | "label""legend"
FieldErrorerrorsArray<{ message?: string } | undefined>
ComponentRenders
FieldSetfieldset
FieldLegendlegend with data-variant
FieldGroupdiv, a @container/field-group
Fielddiv with role="group" and data-orientation
FieldContentdiv flex column for label and description beside a control
FieldLabelLabel (label), pass for to link the control
FieldTitlediv with label styling, for a title that is not a label
FieldDescriptionp helper text
FieldSeparatordiv with a Separator, plus centered text when it has content (data-content)
FieldErrordiv with role="alert": the slot, the single message, or a list of unique errors messages