/// Inputs
Field
Form-field wrapper: a caption label, the control, and hint or error messaging with ARIA wired for you.
import { Field } from "@protocore/pds";Basics
Wrap any control in a Field to get a mono uppercase label and a muted hint. Field clones the child to inject a generated id, points the label's htmlFor at it, and wires aria-describedby to the hint — no manual id bookkeeping.
Shown in the operator console.
Error state
Set error to replace the hint with a message rendered in role="alert", and mark the control invalid (aria-invalid). Set required to append the required marker to the label.
Must be a valid https:// URL.
In a form
Stack Fields to build a form. Each wraps a different control — here an Input and a Textarea — and manages its own label/hint wiring independently.
When to use
Use Field around *every* labelled form control — Input, Textarea, Select, NumberInput, and friends. It exists so labels, hints, error text, and the ARIA that ties them together are consistent and correct across every form in the system.
- Field auto-wires the child by cloning it. If you need to point the label at a control you render yourself (or a composite that doesn't forward
id), pass an explicithtmlForand set the matchingidon the control. - Keep the label a short noun phrase and the hint one line; move anything longer into surrounding prose.
- Field is a *wrapper*, not a control — it never renders an input itself.
Do & don't
Do
- Wrap every labelled control in a Field so ARIA wiring stays consistent.
- Use hint for always-on guidance and error for validation failures.
- Mark genuinely-required fields with required, not with a "(required)" suffix in the label.
- Pass htmlFor when Field can't auto-wire the child (custom composites).
Don't
- Don't hand-roll <label> + id pairs when Field will wire them for you.
- Don't show hint and error at once — error replaces the hint by design.
- Don't put the error message only in colour; the role="alert" text carries it.
- Don't nest interactive controls Field can't reach as the single child.
Accessibility
- The label's `htmlFor` targets the control's `id` (generated when you don't supply one).
- Hint and error are linked to the control via `aria-describedby`.
- `error` sets `aria-invalid` on the control and is announced through `role="alert"`.
- Auto-wiring clones the single child element; pass `htmlFor` for controls that don't accept an injected `id`.
Mobile (React Native)
Preview. @protocore/pds-mobile ships the React Native sibling of Field. It mirrors the web API where React Native allows; the package is a preview with no device-level QA yet, so pin it and expect small changes.
Import it from the mobile package (not @protocore/pds), inside a <PdsProvider> — there is no stylesheet, so style (a ViewStyle) replaces className and every value comes from the theme:
import { Field } from "@protocore/pds-mobile";Parity with web. The labelled form-field wrapper — label, control, hint, and error.
- RN has no
htmlFor/id, so the label gets anativeIDand the child control is cloned withaccessibilityLabelledBy. errorreplaceshintwhen present and is announced to assistive tech.
<Field label="Service name" error={err} required>
<Input value={name} onChangeText={setName} invalid={!!err} />
</Field>Field props
| Prop | Type | Default | Description |
|---|---|---|---|
children * | ReactNode | — | The control element (Input, Select, Textarea…). Cloned with `id`/`aria-describedby` when `htmlFor` is absent. |
className | string | — | |
error | ReactNode | — | Error message; when present it replaces the hint and is announced via `role="alert"`. |
hint | ReactNode | — | Helper text shown below the control (muted). |
htmlFor | string | — | Explicit id of the control the label points at. Omit to auto-wire the child via a generated id. |
label | ReactNode | — | Field label — rendered as a mono uppercase caption. |
required | boolean | — | Append a required marker to the label. |
style | CSSProperties | — |