# FormFieldEditorial

> Single field for editorial contact flows: a text, email, tel, textarea or select control on the shared FieldShell label, status and helper chrome.

- Status: stable
- Group: form
- Page: https://www.digitaltableteur.com/design-system/components/form-field-editorial
- Contract: https://www.digitaltableteur.com/contracts/v1/FormFieldEditorial.contract.json

## When to use

Editorial field wrapper used by ContactFormEditorial; the label, status and helper text come from the shared FieldShell. For standard forms use the inputs' built-in labels; FormField covers group semantics.

## When not to use

The contract records no forbidden uses.

## Look-alikes

The contract names no look-alike with a deciding condition.

## Props

| Prop | Type | Default | Description | Required |
| --- | --- | --- | --- | --- |
| `type` | `"text" \| "tel" \| "email" \| "textarea" \| "select"` | `text` | Control to render; defaults to text. select renders Combobox over a hidden native select element that carries the forwarded ref, name, form and disabled, so the value submits with its form, onChange receives a real change event from that select and onBlur fires when focus leaves the field; defaultValue is an uncontrolled initial value. aria-describedby is passed to the Combobox trigger; other select attributes are dropped. | No |
| `children` | `ReactNode` | none | Option elements for type="select", parsed into Combobox options; an option with an empty value becomes the placeholder. | No |
| `label` | `string` | none | Field label, rendered by the shared FieldShell Label (Combobox label for select). | Yes |
| `error` | `string` | none | Error message. | No |
| `required` | `boolean` | none | Whether the field is required. | No |
| `className` | `string` | none | Additional className. | No |
| `id` | `string` | none | Field ID. When omitted it is generated from the label: lowercased, accents folded (Sähköposti becomes sahkoposti), spaces hyphenated and letters of any script kept; a label with no letters or digits gets a unique generated id. Two fields with the same label still need an explicit id. | No |
| `helperText` | `string` | none | Supporting text under the field, linked with aria-describedby (select passes it to Combobox). Use it, for example, to say why a read-only value is fixed. | No |
| `status` | `FieldStatus` | none | Semantic state: colours the border and styles statusMessage. `error` overrides it. | No |
| `statusMessage` | `string` | none | Message under the field for `status`, above the helper line. | No |
| `actions` | `FieldAction[]` | none | Icon buttons at the end of the label row: each runs an operation or opens a menu. | No |

## Variants

- Available types: `text`, `tel`, `email`, `textarea`, `select` (default `text`).

## Invalid combinations

- MUST: `children` set without `type`. Whenever `children` is accepted by FormFieldEditorialProps, `type` must also be present.

## Keyboard

The contract records no keyboard interaction.

## Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

| Level | Rule | How it is checked |
| --- | --- | --- |
| MUST | `children` set without `type`. Whenever `children` is accepted by FormFieldEditorialProps, `type` must also be present. | Checked by the MCP tool validate_component_usage. |
| MUST | ARIA: Text, email, tel and textarea controls set aria-invalid from the error status and aria-required when required. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | ARIA: Aria-describedby chains the status message, the helper text and any aria-describedby the caller passes, in that order. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | ARIA: Type="select" delegates its ARIA to Combobox; the hidden native select that carries the ref, name and form is hidden, aria-hidden and out of the tab order, and the caller's aria-describedby is added to the combobox trigger. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | Required stories produce no axe violations at the configured severity. | Automated by `npm run test:stories:matrix:ci`. WCAG 2.5.8. |
| MUST | The accessibility tree (role, name, state) matches the committed snapshot for every required story. | Automated by `npm run test:stories:matrix:ci`. WCAG 1.3.1, 4.1.2. |
| MUST | The component remains legible and operable under a real browser forced-colors: active pass. | Automated by `npm run test:stories:hc`. |
| MUST | A human completed an end-to-end accessibility review of this component. | Manual review, last on 2026-11-04. |
| MUST NOT | Maintainers: Do not bypass design tokens or skip forced-colors verification at beta. | Release review; not machine-checked. |

## Install and import

- In-repo only. FormFieldEditorial is not exported from `@digitaltableteur/react`, so there is no public import path.

## Links

- Machine-readable contract (Design System Contract 1.0): https://www.digitaltableteur.com/contracts/v1/FormFieldEditorial.contract.json
- Markdown version of this page: https://www.digitaltableteur.com/design-system/components/form-field-editorial.md
- Component index as JSON: https://www.digitaltableteur.com/design-system/components.json
- All components: https://www.digitaltableteur.com/design-system/components
- Source: The implementation lives in a private repository. This page, its Markdown twin and the contract are generated from it at build time and are the public source of truth.
