Skip to content

Accessibility

A field pairs a native form control — a text <input>, or a <button> that opens a picker — with a label, helper text, and an error message. It has no single WAI-ARIA interaction pattern of its own: it leans on native form-control semantics and label association, and meets WCAG 2.1 AA. An accessible field gives its control a programmatically associated label that stays visible while the user types, links its helper and error text to that control, and exposes the required, invalid, and disabled states to assistive technology — so the field’s purpose, state, and any error are clear whether the user sees it, hears it, or tabs to it.

  • The control, its label, helper text, and error message — including their hover, focus, disabled, and invalid states — must maintain accessible contrast on every supported surface. Source: WCAG 1.4.3 Contrast (Minimum).
  • Error and success states must never be conveyed by colour alone — always pair the colour with an icon and text, such as the error message or a helper hint. Source: WCAG 1.4.1 Use of Color.
  • Focus styles must stay visible, meet contrast requirements on every supported surface, and be clearly distinguishable from hover — a colour change alone is not enough. Source: WCAG 2.4.7 Focus Visible.
  • Use semantic colour tokens (e.g. foreground/neutral/default) rather than fixed values, so the component adapts correctly across themes and surfaces.
  • Provide a clear, concise label and surface format hints in the helper text. Keep the label visible while the user types rather than relying on a placeholder, and hold error states until the user leaves the field (on blur) rather than flagging them mid-entry.

The control is a native <input> or <button>, so it carries its own role, keyboard operation, and focus behaviour for free — a user can always move to it and Tab or Shift + Tab away again, with no keyboard trap. Add ARIA only to supply what native markup can’t infer on its own: the label association, the link from helper and error text to the control, and the required and invalid states. Keep the label programmatically associated and visible rather than leaning on the placeholder. Interactive targets must be at least 44 px high for comfortable touch use — comfortably clearing the WCAG AA minimum. Source: WCAG 2.5.8 Target Size (Minimum). Each element’s role, accessible name, and state are in the Labelling elements section below.

Give every element the role, name, and state assistive technology needs.

Label

The label — the static .tng-field-label above the control, or the floating .tng-field-control-label — must be programmatically associated with the control via for / id, so the control takes its accessible name from it. A placeholder is not a label: never leave the control’s name to placeholder text alone, and keep the label rendered (the floating variant shrinks, it doesn’t disappear) while the user types.

Control

The interactive .tng-field-control-input (<input>) or .tng-field-control-button (<button>) is a native form control, so its role and value come for free. Its accessible name comes from the associated label; decorative icons inside the control — the chevron, a leading icon — are marked aria-hidden="true" so they don’t pollute that name.

Required

For inputs, the native required attribute both enforces and announces the required state. When you show that state with the .is-required class instead — e.g. on a control button, which has no native required — also add aria-required="true" to the control so assistive technology announces it.

Validation & error text

The .is-invalid class is visual feedback only. Pair it with aria-invalid="true" on the control, and link the .tng-field-error message to the control with aria-describedby so it’s announced with the field. Link the .tng-field-info helper text the same way, so format hints are read out too. (Native HTML validation applies the invalid state automatically, so you don’t need .is-invalid alongside required.)

Disabled

The native disabled attribute removes the control from the tab order and communicates the disabled state automatically — no extra ARIA is needed. Prefer it over a class-only disabled style, which would leave the control focusable and unannounced.

Source: WCAG 4.1.2 Name, Role, Value.