Forms

Field

The layout around a control: label, description, error. FieldSet and FieldGroup stack them; orientation sets the row.

packages/design-system/components/ui/field.tsx

Examples

Project

We read every one.

A fieldset with a legend and two fields
Invalid: data-invalid on the field, aria-invalid on the control
Horizontal

Anatomy

  1. 01FieldSet and FieldLegend
  2. 02FieldGroup, gap-7
  3. 03Field: label, control, description
  4. 04FieldError, role="alert"

Usage

import {
  Field, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSet,
} from "@repo/design-system/components/ui/field";

<FieldSet>
  <FieldLegend>Project</FieldLegend>
  <FieldGroup>
    <Field data-invalid={!!error}>
      <FieldLabel htmlFor="email">Email</FieldLabel>
      <Input id="email" aria-invalid={!!error} />
      <FieldError errors={[error]} />
    </Field>
  </FieldGroup>
</FieldSet>

Props

PropTypeDefaultDescription
orientation"vertical" | "horizontal" | "responsive""vertical"Responsive is a column that becomes a row when the FieldGroup container is md or wider.
FieldLegend variant"legend" | "label""legend"Label sets it at the label size.
FieldError errors{ message?: string }[]noneDeduplicated; one shows as text, several as a list. Children win if given.
data-invalid"true"noneOn Field, turns the label and text destructive.
classNamestringnoneMerged last with cn(). Use it for layout (width, margin), not to restyle the component.

Guidance

Do

  • Wrap every control in a Field so spacing is the same everywhere.
  • Say what is wrong and how to fix it in the error.

Don't

  • Add margins between fields; FieldGroup spaces them.