NS Design System
v3.0.0 · 257 tokens

17Field

The wrapper that makes a control a form field: label above, help or error below, all wired with aria-describedby. Every control on a real form sits inside one.

Use it for

  • Around every Input/Select/Textarea in a form
  • Error display — the message replaces the help text and is announced via role="alert"

Not for

  • Checkbox/radio/switch — their label wraps the control instead (see those pages)

Label + help

We send lesson updates here.

markup
<div class="ns-field" style="max-inline-size:20rem">
  <label class="ns-field__label" for="f-email">Email address<span class="ns-field__required" aria-hidden="true">*</span></label>
  <input class="ns-input" id="f-email" type="email" aria-describedby="f-email-h" required>
  <p class="ns-field__help" id="f-email-h">We send lesson updates here.</p>
</div>

Error state

Name what is wrong and what to do — never just "invalid".

markup
<div class="ns-field" style="max-inline-size:20rem">
  <label class="ns-field__label" for="f-org">Org ID</label>
  <input class="ns-input ns-input--mono" id="f-org" value="00D5g0000" aria-invalid="true" aria-describedby="f-org-e">
  <p class="ns-field__error" id="f-org-e" role="alert">That ID is 18 characters. This one has 9.</p>
</div>

Accessibility contract

  • The label is a real
  • aria-invalid drives the error styling, so seen and announced state cannot drift
  • The error is announced immediately (role="alert") because the user has already left the field when validation lands