# Field

> One form question: its label, the control, a hint and any error.

- **Level**: molecule · **Status**: stable · **Role**: input
- **Import**: `import { Field, FieldRoot, FieldControl, FieldDescription, FieldError, FieldLabel } from "@rrios-forge/ui/molecules/field";`
- **Source**: `packages/ui/src/molecules/field`

**Purpose.** The canonical accessible form composition. `Field` is the molecule that *binds* a label, a control, a description and an error into a single semantic unit, owning the wiring (`id`, `htmlFor`, `aria-describedby`, `aria-invalid`, `aria-required`) so the consumer never forgets it.

**When to use.**
- Any input that needs a visible label (almost always).
- A choice control (radio, checkbox, switch) that participates in a form.
- A composite control (Select, Combobox, DateField, FileDropzone) that should expose the same a11y contract as a plain Input.

**When NOT to use.**
- Inline single-input search bars where the placeholder *is* the label (controversial, but accepted) — use the bare control.
- Toolbar-style toggles where the affordance is a `Switch` without descriptive copy — use the atom directly.
- A list of independent options *not* tied to a label (a permission grid, a settings switchboard) — use `ChoiceGroup` or `SettingsField`.

**Composes with.**
- `Field.Label` (always), `Field.Control` (wraps the input atom), `Field.Description` (intent / hint), `Field.Error` (validation).
- Controls: `Input`, `Textarea`, `Select`, `Combobox`, `Checkbox`, `Radio`, `Switch`, `DateField`, `Slider`, `FileDropzone` — anything that accepts standard ARIA attributes on its rendered DOM element.
- `FormSection` consumes Field as the row unit; `ErrorSummary` aggregates errors that originate in Field.

**Accessibility.**
- `Field.Label` becomes the control's accessible name via `htmlFor` ↔ `id`. Required fields expose `aria-required` automatically.
- `Field.Description` and `Field.Error` are joined into the control's `aria-describedby` so assistive tech reads the hint and the error in order.
- `invalid` propagates `aria-invalid="true"` and triggers the error tone on the control's chrome.
- `disabled` propagates to the control and visually demotes the label without removing it from screen readers.
- Radio / Checkbox / Switch controls keep their native semantics; the molecule never wraps them in extra interactive divs.

**Related patterns.**
- `Patterns/Forms · FieldAnatomy` — the four-slot anatomy this molecule renders.
- `Patterns/Forms · ValidationFlow` — when and where the error appears.
- `Patterns/Feedback · InlineFeedback` — why the error stays next to its cause.
- `Patterns/Composition · AtomToMolecule` — Field as the first molecule a form needs.

## Use it for

- Field with label + helper + error → `Field` + `Input`/`Textarea`/`Select`

## Axes

| Axis | Part | Values | Default | Meaning |
|---|---|---|---|---|
| `orientation` | — | `vertical` `horizontal` | `vertical` | The direction the parts run: a row (horizontal) or a column (vertical); responsive stacks on phones and runs in a row from sm. |
| `disabled` | — | `true` `false` | `false` | Not available: dimmed, skipped by the keyboard, ignores the pointer. |

## Stories

- [Playground](/?path=/story/components-molecules-field--playground) · frame: `/iframe.html?id=components-molecules-field--playground&viewMode=story`
- [With Input](/?path=/story/components-molecules-field--with-input) · frame: `/iframe.html?id=components-molecules-field--with-input&viewMode=story`
- [With Textarea](/?path=/story/components-molecules-field--with-textarea) · frame: `/iframe.html?id=components-molecules-field--with-textarea&viewMode=story`
- [With Select](/?path=/story/components-molecules-field--with-select) · frame: `/iframe.html?id=components-molecules-field--with-select&viewMode=story`
- [With Checkbox](/?path=/story/components-molecules-field--with-checkbox) · frame: `/iframe.html?id=components-molecules-field--with-checkbox&viewMode=story`
- [Invalid](/?path=/story/components-molecules-field--invalid) · frame: `/iframe.html?id=components-molecules-field--invalid&viewMode=story`
- [Disabled](/?path=/story/components-molecules-field--disabled) · frame: `/iframe.html?id=components-molecules-field--disabled&viewMode=story`
- [Required](/?path=/story/components-molecules-field--required) · frame: `/iframe.html?id=components-molecules-field--required&viewMode=story`
- [Density examples](/?path=/story/components-molecules-field--density-examples) · frame: `/iframe.html?id=components-molecules-field--density-examples&viewMode=story`
- [Accessibility](/?path=/story/components-molecules-field--accessibility) · frame: `/iframe.html?id=components-molecules-field--accessibility&viewMode=story`

## Patterns consulted

- Patterns/Forms · FieldAnatomy
- Patterns/Forms · ValidationFlow
- Patterns/Forms · ChoiceControls
- Patterns/Feedback · InlineFeedback
- Patterns/Composition · AtomToMolecule

## Decisions that name it

- ADR-004 — Migrate boolean configuration props to semantic axes
- ADR-006 — Geometry and typography signature
- ADR-035 — Motion grammar: the gate before motion, slop by repetition, and what reduced motion keeps

## Always

- Tokens only (R04); variants are semantic axes, never appearance (R02).
- Typography and actions are Poesía atoms, never raw HTML with utilities.
- Vibrant panes need a ground and never nest (ADR-027).
