Field
A field wraps a button or input with a label, helper text, and error message. The control is the interactive shell — available as a button or an input — and the field adds the surrounding label and helper structure.
Ready to use
The Field is a fundamental UI element that allows users to enter, edit, and interact with single-line text data. It is the primary vehicle for data collection in forms and search interfaces, and is fully responsive across all viewports.
Anatomy
Section titled “Anatomy”- Field
- Label
- Input
- Helper text
- Helper icon
When to use it
Section titled “When to use it”Use the field when:
- You need to collect short-form data (Name, Email, Password).
- The expected input is a single line of text.
Avoid the field when:
- The user needs long-form text — use a Textarea instead.
- The input is a choice from limited pre-defined options — use a Dropdown, Radio Group, or Checkbox.
- The input is a date or number — use specialised inputs that can leverage native mobile keyboards and validation.
Properties
Section titled “Properties”State
Rested, Active, Hover, Focused, Disabled, Error, and Success. The focus state shows a 2 px outline; error pairs a coloured border with helper text and an icon so the message reads without colour alone.
Filled
Tracks whether the field carries a value. When filled, the label sits above the input as a compact eyebrow; when empty, the larger label sits inside the field as the placeholder hint.
Required
A boolean that surfaces the required marker beside the label. Keep the visible cue consistent with the form’s overall pattern for required fields.
Helper text
Optional one-line text beneath the input, used to communicate format hints or examples. Replace it with the error or success message when validation runs.
Helper icon
The small info icon paired with the helper text. Decorative — it reinforces the helper message and swaps to the matching error or success glyph when validation runs.
Optional icon
A leading icon slot, used sparingly to clarify intent (a magnifying glass for search, a lock for password). Default off — only enable it when the icon adds meaning.
Platform considerations
Section titled “Platform considerations”Desktop
The field stretches to fit its column and respects keyboard focus management. Width should match the expected content length so the input doesn’t feel arbitrary.
Tablet
Same layout as desktop. Touch and pointer mix here — make sure the helper text and label remain readable when the on-screen keyboard pushes the form upward.
Mobile
The label persists above the input even when the keyboard opens. Use the right inputmode and autocomplete so mobile keyboards surface the right glyphs.
Best practices
Section titled “Best practices”Consistency in input fields reduces cognitive load — every input must have a visible label and a clear focus indicator.
Do
Provide a clear, concise label above the input, surface format hint examples in the helper text, group related inputs logically inside form sections, and lean on native HTML elements so focus order and accessibility come for free.
Don't
Don’t hide the label while the user is typing, don’t trigger error states prematurely (wait for blur), and don’t rely on colour alone for error or success — always include an icon or helper text.
Content guidelines
Section titled “Content guidelines”The label should name exactly the data you want — “Email address” beats “Email”, “Mobile number” beats “Phone”. Use the helper text to show the expected format with a real example so the user can match the pattern as they type. Error messages should name what went wrong and how to fix it (“Pick a number between 1 and 99”) instead of restating the field. Width should mirror the expected content length so a postcode field doesn’t sprawl like a long-name field.
Styles
Section titled “Styles”A field wraps a button or input with a label, helper text, and error message. The tng-field element is the wrapper; the tng-field-control element is the interactive shell, available as a button or an input.
A field wraps a control with a label, helper text, and error message.
<div class="tng-field"> <label class="tng-field-label">Username</label> <div class="tng-field-control"> <input class="tng-field-control-input" type="text" /> </div> <div class="tng-field-info"> <i class="tng-icon icon-info"></i> <span>Helper text for the input field.</span> </div> <div class="tng-field-error"> <i class="tng-icon icon-error"></i> <span>Error message if applicable.</span> </div></div>Control
Section titled “Control”The control is the base interactive element used in form fields, available as a button or input.
Button
Section titled “Button”Use a control button to trigger custom dropdowns, date pickers, or other interactive elements.
<div class="tng-field-control"> <button class="tng-field-control-button">Select an item</button></div>Use an input control to allow users to enter text or data.
<div class="tng-field-control"> <input class="tng-field-control-input" type="text" /></div>Elements
Section titled “Elements”Icon Button
Section titled “Icon Button”<div class="tng-field-control"> <input class="tng-field-control-input" type="text" /> <button class="p-absolute tng-icon-button is-ghost" aria-label="More info" > <i aria-hidden="true" class="tng-icon icon-info"></i> </button></div><div class="tng-field-control"> <i aria-hidden="true" class="tng-icon icon-car"></i> <button class="tng-field-control-button">Select model</button> <i aria-hidden="true" class="tng-icon icon-chevron-down"></i></div>A dynamic label can be combined with an input control to provide context about the expected input. The label will shrink and move above the input field when the user focuses on the input.
<div class="tng-field-control"> <label class="tng-field-control-label">Email address</label> <input class="tng-field-control-input" type="text" /></div><div class="tng-field-control"> <label class="tng-field-control-label is-lg">Email address</label> <input class="tng-field-control-input" type="text" /></div>Required
Section titled “Required”In case of an input control you can rely on the native HTML required attribute to indicate that a form control is required. If that’s not an option, you can use the is-required class anywhere within the control to show the required state.
<div class="tng-field-control"> <button class="tng-field-control-button is-required"> Select an item </button> <i aria-hidden="true" class="tng-icon icon-chevron-down"></i></div><div class="tng-field-control"> <label class="tng-field-control-label">Email address</label> <input class="tng-field-control-input" type="text" required /></div>States
Section titled “States”Disabled
Section titled “Disabled”<div class="tng-field-control"> <input class="tng-field-control-input" type="text" disabled /></div><div class="tng-field-control"> <button class="tng-field-control-button" disabled> Select an item </button></div>Invalid
Section titled “Invalid”<div class="tng-field-control is-invalid"> <input class="tng-field-control-input" type="text" /></div>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.
For designers
Section titled “For designers”- 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.
For developers
Section titled “For developers”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.
Labelling elements
Section titled “Labelling elements”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.