Open any design file for a product and the screens look the same: a table full of tidy rows, a chart with a confident line, a profile with a photo. Real products spend a surprising share of their life somewhere else. A new user has nothing yet. A request is in flight. A filter matches nothing. A service is down.
Those moments are where people decide whether a product can be trusted. They are also the screens developers end up inventing alone, because nobody drew them.
The states every screen has
For each screen, ask which of these it can be in:
- Ideal: all the data, as drawn in the design file.
- Empty: there is no data, and there are different reasons for that.
- Loading: the data is on its way.
- Partial: some of it arrived, some did not.
- Error: something failed.
- Restricted: the person is not allowed to see it.
If a screen has only the first, it is a sketch, not a design.
Empty states
There are three kinds, and they need different words.
First use. Nothing has been created yet. This is the best moment to teach. Say what the screen is for, show what it will look like once it is filled, and offer one clear action.
Weak: "No data."
Better: "No invoices yet. Create your first invoice and its payment status will appear here." with a button labelled "Create invoice".
No results. The person searched or filtered and nothing matched. Repeat what they asked for, and offer a way out: clear the filters, widen the date range, check the spelling.
Cleared. The work is finished, as in an empty inbox. A short confirmation is enough, and a quiet tone suits it.
An illustration is optional. The explanation and the action are not.
Loading states
How long a wait lasts decides what to show.
- Under about a tenth of a second feels instant. Show nothing.
- Up to a second or so: do not flash a spinner for a moment and remove it. Wait about a third of a second before showing any indicator.
- Longer: show that something is happening. If the shape of the content is known, a skeleton (grey blocks where the content will go) feels faster than a spinner and prevents the page from jumping when the data arrives. Use a spinner for short waits where the shape is unknown.
- Around ten seconds or more: show progress, explain what is taking time and let the person leave or cancel.
Keep the layout stable. If the skeleton is a different height from the content, the page will jump anyway.
Partial states
Dashboards often pull from several sources. If one fails, do not blank the whole screen. Show what arrived and mark the missing part clearly: "Payments are unavailable right now. Showing data from 09:00." Put the problem next to the thing it affects, not in a banner far away.
Error states
A useful error message does four things:
- Says what happened, in plain words.
- Says what it affects.
- Says what the person can do, and offers the action as a button.
- Keeps whatever they had typed.
Weak: "Error 500."
Better: "We could not save your changes. Nothing was lost. Check your connection and try again." with a "Try again" button.
Treat the two kinds of error differently. A validation error is the person's to fix, so point at the field and say what is expected. A system error is not their fault, so do not make it sound like it is. For failures that persist, give a short reference they can quote to support.
Restricted states
When someone cannot see something, say so, and say who can: "Billing is visible to account owners. Ask an owner to grant you access." A blank screen or a vanished menu item looks like a bug.
How to design them without doubling the work
Make a small table for each screen, with one row per state: what the person sees, what the words say and what the action is. It takes minutes per screen and gives developers everything they need.
Then test the ideal state with awkward data, not just tidy samples:
- zero items, one item and thousands;
- a very long name and a missing name;
- a date in the past, today and far in the future;
- a number with many digits, and a negative one.
Most layout failures show up here, before any code is written.
A short checklist
- Does every list, table and chart have an empty state with an explanation and an action?
- Is there a loading state that keeps the layout stable?
- What happens when part of a screen fails?
- Does every error say what happened, what it affects and what to do?
- Are restricted views explained?
- Are all of these in the handoff, not left for developers to invent?