Forms

Accessible, themeable inputs, selects, checkboxes, validation states and form layout.

1 min readv1

Recipes for form controls#

TypeScript
components: {
  label: "d=block; fts=13px; ftw=600; mb=6px",
  input: "w=100%; p=10px 12px; bdrd=8px; bd=1px solid #cbd5e1; bgc=#fff; cl=#0f172a; otl=none; ts=border-color .15s, box-shadow .15s; placeholder:cl=#94a3b8; focus:bdc=$color.brand; focus:bxsh=0 0 0 3px rgba(79,82,217,.2); user-invalid:bdc=#dc2626; disabled:opc=.6; dark:bgc=#0f172a; dark:bd=1px solid #334155; dark:cl=#e2e8f0",
  hint: "d=block; fts=12px; cl=#64748b; mt=6px",
  field: "d=flex; flxd=column",
}

A complete sign-up form#

HTML
<form nib="d=grid; g=14px; w=320px" onsubmit="return false">
  <label nib="d=flex; flxd=column; g=6px; fts=13px; ftw=600">Email
    <input type="email" required placeholder="you@example.com" nib="p=10px 12px; bdrd=8px; bd=1px solid #cbd5e1; otl=none; ftw=400; placeholder:cl=#94a3b8; focus:bdc=#4F52D9; focus:bxsh=0 0 0 3px rgba(79,82,217,.2); user-invalid:bdc=#dc2626">
  </label>
  <label nib="d=flex; flxd=column; g=6px; fts=13px; ftw=600">Plan
    <select nib="p=10px 12px; bdrd=8px; bd=1px solid #cbd5e1; ftw=400; bgc=#fff; cl=#0f172a"><option>Starter</option><option>Team</option></select>
  </label>
  <label nib="d=flex; ali=center; g=8px; fts=13px; acc=#4F52D9"><input type="checkbox" required> I accept the terms</label>
  <button nib="p=10px; bdrd=8px; bd=none; bgc=#4F52D9; cl=#fff; ftw=600; cur=pointer; hover:bgc=#3A3DBF">Create account</button>
</form>

Validation states#

user-invalid: applies only after the user has interacted with the field, so a form does not start out red. Use invalid: if you want the state immediately.

Accessibility checklist#

  • Every input has a visible <label> (or aria-label).
  • Focus is visible: focus:bxsh=… or focus-visible:otl=….
  • Error text is linked with aria-describedby, not only coloured red.
  • Hit targets are at least 40px tall on touch devices: mnh=40px.

Next steps#