States

An interface spends most of its life not in the happy path. These are the names for everything in between.

01

Loading

Work-in-progress feedback. For unknown waits, a spinner or progress; for content shapes you can predict, a skeleton. The job is to say “something is happening,” not to entertain.

Say it precisely“Show a loader.”“Show a determinate progress bar if duration is known; otherwise a spinner after a 300ms delay to avoid flicker.”

See the difference
02

Empty

A zero-content state — no results, nothing created yet. A good empty state explains why it's empty and offers the single next action, instead of leaving a void.

No results yet.
Try a different filter.

Say it precisely“Handle no data.”“Render an empty state with a one-line reason and a primary action — not a blank container.”

See the difference
03

Error

Failure feedback that says what went wrong and how to recover. Place it next to its cause, keep the tone plain, and always offer a way forward — retry, undo, or a fix.

Couldn't save changesCheck your connection and try again.

Say it precisely“Show an error.”“Show an inline error beside the field: what failed, why, and a retry — never a generic ‘something went wrong’.”

See the difference
04

Disabled

A control that's temporarily unavailable — visibly present but inert. The hard part is telling the user why, so the disabled state never becomes a dead end.

Complete required fields to enable.

Say it precisely“Grey it out.”“Disable the button with aria-disabled and a tooltip stating the unmet condition; re-enable when met.”

See the difference
05

Skeleton

Placeholder shapes that mirror the eventual layout while it loads. Because the structure stays put, content swaps in without a jarring reflow — calmer than a spinner for known shapes.

Say it precisely“Add shimmer placeholders.”“Show skeleton blocks matching the final card layout; cross-fade to content on load, no reflow.”

See the difference