Field
The wrapper around any form control: label, control, and one line under it (hint or error). React <Field> (packages/ui/src/components/Field.tsx) renders .acrm-field > label.acrm-field-label + children + span.acrm-field-hint / span.acrm-field-error (apps/web/src/ds.css). Error wins over hint — only one line is ever shown.
When to use
- Every labelled control in a form, drawer or dialog: Input, Textarea, Select, Date field, Checkbox group, Tag input, Slider.
- A control that needs a format hint ("8 digits") or a validation message.
- A label with an inline extra on the right (
labelExtra— an icon or help affordance, pattern from DrawerField).
When not to use
- A control in a table cell, rail row or toolbar where the column header or row label already names it — the label would repeat.
- Search inputs in a top bar — they carry an
aria-labeland a placeholder, not a visible label. - Inline
<label style={…}>or a page-level.xyz-label— the label typography is one token (--label) and lives here.
Anatomy
- Container
.acrm-field:display: grid; gap: var(--sp-1); takes the column width — it has no width of its own. - Label
.acrm-field-label:font: var(--label)(500 12px/22px--font-display, Manrope — AD 25 Aug 2026),color: var(--fg-secondary); rendered asflexwithgap: var(--sp-2)solabelExtrasits inline after the text. - Hint
.acrm-field-hint:font: var(--hint)(400 12px/1.45),color: var(--fg-muted)— the only class for help text under a field (.acrm-field-helpwas retired 26 Aug 2026). - Note
.acrm-note: the same typography (font: var(--hint),color: var(--fg-muted)) with no Field around it — see below. - Error
.acrm-field-error:font: var(--hint),color: var(--critical-ink). - Props:
label,labelExtra,hint,error,className,style,children; no size or layout props.
Best practices
Do
- One Field per control; stack fields with the form's own gap, not with margins on the label.
- Use the hint for format and scope ("8 digits, verified in the register"), the error for what to fix.
- Pair the message with the frame:
erroron Field plus.is-erroron the Input so both agree. - Give a group explanation above the first field of the group and name the fields it covers ("Position, initials and phones fill the e-mail signature").
Don't
- Hint and error at once — Field shows only the error; do not stack a second line under it.
- Explanatory paragraphs under a field — nobody reads them; fix the label or the control instead.
- A label in capitals or ending with a colon.
- Hiding the label to save space in a form — use
aria-labelonly for search-type inputs outside forms.
Content
- Label: short noun in sentence case ("Phone", "Industry"); no colon, no period.
- Hint: one clause, format or limit, no period unless a full sentence ("8 digits").
- Error: one sentence, what is wrong and how to fix it, with a period ("Enter a valid e-mail address.").
- A group note goes above the group, lists the fields it applies to, and is never placed under the last field.
- Optional fields are not marked "(optional)"; required ones are not marked with
*— the form's validation tells.
.acrm-note — the free-standing sibling
.acrm-note (apps/web/src/ds.css) is quiet descriptive text that sits next to a value, not under a control: the file size on an attachment chip, "uploading…" on a chip on its way to a draft, the subtitle of a printed document, the body preview of a saved prompt, the one line an empty thread explains itself with.
Same role as the hint — explanation, not a value — so it carries the same token --hint (400 12px/1.45, AD 26 Aug 2026: weight 400, because 500 would be louder than the value it describes). The only difference is who sets it: .acrm-field-hint is written by <Field> under a control, .acrm-note is written by the caller anywhere.
Introduced 9 Sep 2026 (AI-A1). Before that, six places wrote className="sub" and picked up the global .sub of the navigation row (apps/web/src/ds/segment-screen.css) — 28px height, padding, border-radius, cursor: pointer and a hover background on a piece of text. .sub stays with navigation; the descriptor got its own name. Deleting .sub was not an option: it is a port of the canon (_ds/segment-screen.css) and ds:sync-check then reports it MISSING against those six files.
Scoped overrides are allowed where a surface has its own scale — .aichat-empty .acrm-note (--subtitle, an empty state speaks up), .sml-title .acrm-note (the printed contract has its own type scale). A scoped override that only repeats --hint is noise; delete it.
Do not use .acrm-note for a hint under a control — that is <Field hint>, and Field owns the error/hint precedence.
Related
input,textarea,select,date-field,checkbox— controls that sit inside.input-with-icon-kbd— the only text field that usually goes without a Field (search)..acrm-note— the same typography outside a Field;.sub(navigation row) is not a text style and never was.- Stories:
components--field--default,components--field--variants,components--field--states,components--field--composition; legacycomponents--inputs--fields.
Source: docs/text-field/field.usage.md · GitLab