Field

Slot-based label + control + description/error. Works with or without a form input.

With a control

We'll never share it.

<Field>
  <FieldLabel>Email</FieldLabel>
  <FieldControl>
    <Input type="email" placeholder="you@example.com" />
  </FieldControl>
  <FieldDescription>We'll never share it.</FieldDescription>
</Field>

Without a control — just header + subtext

Choose how you want to hear from us.

<Field>
  <FieldLabel>Notifications</FieldLabel>
  <FieldDescription>Choose how you want to hear from us.</FieldDescription>
</Field>

Inline action

Unsubscribe any time.

<Field>
  <FieldLabel>Newsletter</FieldLabel>
  <FieldControl direction="horizontal">
    <Input placeholder="you@company.com" />
    <Button>Subscribe</Button>
  </FieldControl>
  <FieldDescription>Unsubscribe any time.</FieldDescription>
</Field>

Error

<Field invalid>
  <FieldLabel>Password</FieldLabel>
  <FieldControl>
    <Input type="password" defaultValue="abc" />
  </FieldControl>
  <FieldError>Must be at least 8 characters.</FieldError>
</Field>

Horizontal orientation

Public display name.

<Field orientation="horizontal">
  <FieldLabel>Name</FieldLabel>
  <FieldControl>
    <Input placeholder="First Last" />
  </FieldControl>
  <FieldDescription>Public display name.</FieldDescription>
</Field>

Stacked form (FieldGroup)

Work email is best.

<FieldGroup>
  <Field>
    <FieldLabel>Name</FieldLabel>
    <FieldControl><Input placeholder="First Last" /></FieldControl>
  </Field>
  <Field>
    <FieldLabel>Email</FieldLabel>
    <FieldControl><Input type="email" /></FieldControl>
    <FieldDescription>Work email is best.</FieldDescription>
  </Field>
  <Field>
    <FieldLabel>Message</FieldLabel>
    <FieldControl><Textarea /></FieldControl>
  </Field>
</FieldGroup>

Gap scale

Loose internal spacing.

Packed in.

<FieldGroup gap="3">    // tighter form stack (10px in Compact)
  <Field gap="2">      // default Field spacing — 6px
    <FieldLabel>Name</FieldLabel>
    <FieldControl><Input /></FieldControl>
    <FieldDescription>Default internal spacing.</FieldDescription>
  </Field>
  <Field gap="1">      // very tight (2px)
    <FieldLabel>Email</FieldLabel>
    <FieldControl><Input type="email" /></FieldControl>
    <FieldDescription>Packed in.</FieldDescription>
  </Field>
</FieldGroup>

Slots

ExportRole
FieldContainer. Props: invalid, orientation ('vertical' | 'horizontal'), id.
FieldLabelReads id from context → sets htmlFor. Destructive color when Field is invalid.
FieldControlWraps the control. Auto-wires id + aria-describedby + invalid onto the first child. direction: 'vertical' | 'horizontal' for inline actions.
FieldDescriptionMuted subtext. Hidden when the Field is invalid.
FieldErrorDestructive message. role=alert.

Source

packages/react/src/components/field.tsx