Skip to content

Field

A field puts the label above a form control and the hint or the error under it. Text fields, selects, comboboxes and date fields all sit inside one, so every question on a form reads the same way.

Anatomy

The label says what to enter and stays in view while you type. The hint under the control says what a good answer looks like. When the answer is wrong, the error takes the hint's place and says how to fix it.

As printed on the photo page.

Label
13 px on 18 px, weight 500
--text
Label to control
6 px
Count
11 px, aligned figures, at the end of the label row
--text-muted
Control to hint
4 px
--space-1
Hint
12 px on 16 px
--text-muted
Error
12 px on 16 px
--error
Between fields
16 px
--space-4
Between groups
32 px
--space-8

Required answers

Write it in words: (required) after the label, in the muted ink. An asterisk alone means nothing to someone who does not know the convention. A screen reader announces the field as required.

When all the questions on a form are required, say so once above the first field and mark none of them. A sign in form with an email and a password needs no mark at all.

Errors and warnings

An error stops the form. The field takes a red edge, and a sentence under it says what to enter. The error clears as soon as the answer is right.

A warning lets the form go through. Use it for an answer that is valid but worth a second look.

Enter an email address like name@company.com.

This passport runs out before the contract ends.

Error edge
2 px around the control
--error
Warning
12 px on 16 px
--warning-ink

Read only and disabled

A read only field shows an answer you can select and copy but not change, such as the ID of a candidate. It has no fill, so it reads as text. It takes focus and is sent with the form.

A disabled field waits for another answer on the form. It fades to 50 percent, Tab skips it and it is not sent. Its hint says what turns it on.

Choose a country first.

When to check an answer

Check a format when the person leaves the field, and only if they typed something. Check required answers when the form is sent, and show all the errors at once.

Once an error shows, check again on each key, so it clears the moment the answer is right.

Check an answer against the server while the person types, such as an employer that may already be in WerkOS. The hint reads Checking until the answer comes back.

Writing for a field

Write the label as a short noun phrase in sentence case, with no colon or full stop: Date of birth.

Write the hint as one sentence about the answer: its format, where to find it, or why you ask.

Write the error as the fix, in the words of the label: Enter the passport number. Do not tell the person they made a mistake.

Use a placeholder only for an example, and only when the hint does not already give one.

Accessibility

The label element names the control. The error, or the hint when there is no error, is the control's description, so a screen reader reads it after the label.

An error is not announced while someone types. It is read when the field takes focus. After a failed submit, focus moves as the Forms pattern describes. Labels wrap onto a second line and are not cut short.

A field you type in shows focus with a blue ring and a halo. A combobox is a button that opens a list, so it shows focus as a button does, with a blue outline outside its edge.

Permitted and not permitted

Permitted

  • A label above the control that stays while you type

    The person can check the question after answering it.

Not permitted

  • A placeholder as the only label

    It disappears on the first key, and the person has to delete the answer to see the question.

NextText field

Field

Wraps one form control with its label, hint and message, and connects them for assistive technology.

  • Kind: component
  • Page: https://design.werklist.com/components/field
  • Version: 2.1.2

When to use it

  • Around each text field, text area, select, combobox, date field and time field in a form
  • Around radio buttons or checkboxes that answer one question, as a fieldset with a legend

When not to use it

  • A search field in a toolbar: it has no visible label, and its placeholder gives its name
  • A label beside the control: the label always sits above it

Rules

  • Check a format when the person leaves the field, and only when it holds a value
  • Check required answers when the form is sent, and show every error at once
  • Once an error shows, check again on each key so it clears at once
  • Check an answer that depends on the server while the person types. The hint reads Checking until the answer comes back
  • The form uses its own messages, never the browser's

Anatomy

  • Label: 13 px on 18 px, weight 500 (--text)
  • Required word: (required) after the label, 13 px on 18 px, weight 400, hidden from screen readers (--text-muted)
  • Count: 11 px on 16 px, aligned figures, at the end of the label row, written 412/500 and read as 412 of 500 characters (--text-muted)
  • Label to control: 6 px
  • Control: described on the page of each control
  • Control to message: 4 px (--space-1)
  • Hint: 12 px on 16 px, weight 400 (--text-muted)
  • Error: 12 px on 16 px, no icon (--error)
  • Warning: 12 px on 16 px, no icon (--warning-ink)
  • Between fields: 16 px (--space-4)
  • Between groups: 32 px (--space-8)
  • Form column: at most 768 px

States

  • Required: (required) follows the label, and the control carries aria-required="true" (--text-muted)
  • Error: The error replaces the hint, the control takes a 2 px edge in the error colour and aria-invalid="true", and the form is not sent (--error)
  • Warning: The warning replaces the hint, and the form can be sent (--warning-ink)
  • Read only: No fill, no ring and no side padding, with the value in full ink. It takes focus and is sent with the form (--text)
  • Disabled: The control fades to 50 percent, Tab skips it and it is not sent. The label and the hint keep their ink, and the hint says what turns it on

Keyboard

  • Tab: Moves to the next control in the order the form shows them

Accessibility

  • A label element whose for attribute points at the control's id
  • aria-describedby lists the message while one shows, otherwise the hint, and the count where there is one
  • aria-invalid="true" while an error shows
  • aria-required="true" on a required control. The visible word is hidden from screen readers so it is not read twice
  • A message carries no role="alert". It is read when the control takes focus
  • After a failed submit, focus moves as the Forms pattern describes, at /patterns/forms
  • A field you type in shows focus with a blue ring and a halo. A combobox is a button that opens a list and shows focus as a button does, with a blue outline outside its edge
  • A fieldset and a legend for controls that answer one question together
  • Labels wrap and are not cut short

Content

  • Label: a noun phrase in sentence case with no colon and no full stop, such as Date of birth
  • Hint: one sentence about the answer, ending with a full stop
  • Error: the fix, in the words of the label, ending with a full stop, such as Enter the passport number. It never blames the person
  • Placeholder: an example of the format only, never the label
  • When every field is required: one sentence above the form, All fields are required, and no marks

Tokens

  • --text
  • --text-muted
  • --error
  • --warning-ink
  • --space-1
  • --space-4
  • --space-8

JSON

{
  "title": "Field",
  "path": "/components/field",
  "url": "https://design.werklist.com/components/field",
  "text": "https://design.werklist.com/agent/components/field",
  "summary": "The label, hint and error around a form control, and how required, read only and disabled fields behave.",
  "version": "2.1.2",
  "kind": "component",
  "name": "Field",
  "purpose": "Wraps one form control with its label, hint and message, and connects them for assistive technology.",
  "use": [
    "Around each text field, text area, select, combobox, date field and time field in a form",
    "Around radio buttons or checkboxes that answer one question, as a fieldset with a legend"
  ],
  "avoid": [
    "A search field in a toolbar: it has no visible label, and its placeholder gives its name",
    "A label beside the control: the label always sits above it"
  ],
  "anatomy": [
    {
      "part": "Label",
      "measure": "13 px on 18 px, weight 500",
      "token": "--text"
    },
    {
      "part": "Required word",
      "measure": "(required) after the label, 13 px on 18 px, weight 400, hidden from screen readers",
      "token": "--text-muted"
    },
    {
      "part": "Count",
      "measure": "11 px on 16 px, aligned figures, at the end of the label row, written 412/500 and read as 412 of 500 characters",
      "token": "--text-muted"
    },
    {
      "part": "Label to control",
      "measure": "6 px"
    },
    {
      "part": "Control",
      "measure": "described on the page of each control"
    },
    {
      "part": "Control to message",
      "measure": "4 px",
      "token": "--space-1"
    },
    {
      "part": "Hint",
      "measure": "12 px on 16 px, weight 400",
      "token": "--text-muted"
    },
    {
      "part": "Error",
      "measure": "12 px on 16 px, no icon",
      "token": "--error"
    },
    {
      "part": "Warning",
      "measure": "12 px on 16 px, no icon",
      "token": "--warning-ink"
    },
    {
      "part": "Between fields",
      "measure": "16 px",
      "token": "--space-4"
    },
    {
      "part": "Between groups",
      "measure": "32 px",
      "token": "--space-8"
    },
    {
      "part": "Form column",
      "measure": "at most 768 px"
    }
  ],
  "states": [
    {
      "name": "Required",
      "change": "(required) follows the label, and the control carries aria-required=\"true\"",
      "tokens": [
        "--text-muted"
      ]
    },
    {
      "name": "Error",
      "change": "The error replaces the hint, the control takes a 2 px edge in the error colour and aria-invalid=\"true\", and the form is not sent",
      "tokens": [
        "--error"
      ]
    },
    {
      "name": "Warning",
      "change": "The warning replaces the hint, and the form can be sent",
      "tokens": [
        "--warning-ink"
      ]
    },
    {
      "name": "Read only",
      "change": "No fill, no ring and no side padding, with the value in full ink. It takes focus and is sent with the form",
      "tokens": [
        "--text"
      ]
    },
    {
      "name": "Disabled",
      "change": "The control fades to 50 percent, Tab skips it and it is not sent. The label and the hint keep their ink, and the hint says what turns it on"
    }
  ],
  "keys": [
    {
      "key": "Tab",
      "action": "Moves to the next control in the order the form shows them"
    }
  ],
  "accessibility": [
    "A label element whose for attribute points at the control's id",
    "aria-describedby lists the message while one shows, otherwise the hint, and the count where there is one",
    "aria-invalid=\"true\" while an error shows",
    "aria-required=\"true\" on a required control. The visible word is hidden from screen readers so it is not read twice",
    "A message carries no role=\"alert\". It is read when the control takes focus",
    "After a failed submit, focus moves as the Forms pattern describes, at /patterns/forms",
    "A field you type in shows focus with a blue ring and a halo. A combobox is a button that opens a list and shows focus as a button does, with a blue outline outside its edge",
    "A fieldset and a legend for controls that answer one question together",
    "Labels wrap and are not cut short"
  ],
  "content": [
    "Label: a noun phrase in sentence case with no colon and no full stop, such as Date of birth",
    "Hint: one sentence about the answer, ending with a full stop",
    "Error: the fix, in the words of the label, ending with a full stop, such as Enter the passport number. It never blames the person",
    "Placeholder: an example of the format only, never the label",
    "When every field is required: one sentence above the form, All fields are required, and no marks"
  ],
  "tokens": [
    "--text",
    "--text-muted",
    "--error",
    "--warning-ink",
    "--space-1",
    "--space-4",
    "--space-8"
  ],
  "rules": [
    "Check a format when the person leaves the field, and only when it holds a value",
    "Check required answers when the form is sent, and show every error at once",
    "Once an error shows, check again on each key so it clears at once",
    "Check an answer that depends on the server while the person types. The hint reads Checking until the answer comes back",
    "The form uses its own messages, never the browser's"
  ]
}

Raw file: https://design.werklist.com/agent/components/field