States and feedback

What it is

Every interactive element exists in several states: idle, hovered or focused, pressed, loading, successful, failed, disabled, empty. Feedback is what the interface does between the action and the result, so the user knows the press registered and can tell progress from a freeze.

Why it matters

Nothing erodes trust faster than uncertainty about whether the machine heard you. A tenth of a second without feedback and people press again — creating the duplicate order, the double subscription, the two support tickets. And it is always the states that were never designed that ship broken: nobody drew the error, so the error renders raw; nobody drew the empty list, so a new user sees a blank area and assumes a bug.

Core ideas

Enumerate the states before designing any of them

Write the list for each element and check it off. Nine states cover most controls; the three that are usually missing are loading, error and disabled-with-a-reason.

Button:  idle | hover | focus | pressed | loading | success | error | disabled
List:    loading | empty | one item | many items | error | stale
Field:   idle | focus | valid | invalid | disabled | read-only

Acknowledge the press immediately

Under about 100 milliseconds the user perceives the response as instant. Beyond that, show a busy state. Never leave a pressed control looking unchanged while work happens.

0-100ms    no indicator needed
100ms-1s   inline busy state on the control itself, control disabled
1-10s      progress indicator plus what is happening
over 10s   background it, tell them it will continue, say how they will hear

Say what failed and keep the input

An error state preserves everything the user typed, names the problem in the interface’s own words, and offers a way forward. A form that clears on failure costs the user the whole task.

Disabled with a reason beats disabled silently

A greyed-out button with no explanation is a dead end; the user cannot tell whether they lack permission, missed a field or hit a bug. Add a one-line reason or allow the press and show the validation.

Design the empty and error states first

They are the states a new or unlucky user sees, they carry the most information per pixel, and they are the ones left to the end. Draw them before the populated state.

Practice

Write a state matrix for one screen

List every interactive element on the screen down the left, the nine states across the top, and fill in what the user sees in each cell. Leave no cell blank.

Done when: every cell is filled, and each of loading, error, empty and disabled-with-reason has a described appearance.

Time one slow action

Pick the slowest action in your product and measure it. Then write what the user sees at 200 milliseconds, at three seconds and at thirty seconds.

Done when: the user can tell progress from a freeze at every one of those three moments, and no state leaves the control looking unchanged.

Common mistakes

  • No loading state — the user presses again and creates a duplicate; fix: show a busy state on the control and disable it while working.
  • Discarding input on error — the whole task is lost and the user leaves; fix: preserve every field and mark only what failed.
  • Silent disabled controls — the user cannot tell why the action is unavailable; fix: attach a one-line reason or validate on press.
  • Undesigned empty and error states — the first impression is a blank area or a raw error string; fix: design both before the populated state.
  • Feedback that does not say what is happening — a generic spinner for a thirty-second job; fix: say what the system is doing and how the user will hear the result.

Go deeper