Prototyping

The UI states checklist: empty, loading, error and more

A UI states checklist for every screen: empty, loading, partial, error, success and edge cases, with examples and a prompt to draft each state.

7 min read

A UI states checklist lists every situation a screen can be in, so that each one gets designed and tested rather than improvised: the ideal state, empty, loading, partial, error, success, and edge cases such as very long text or a missing permission. Run through it for each screen before you build, and again when you review. The table below is a checklist you can copy.

Why screens break in states nobody drew

Design reviews tend to happen on the ideal state: a list with eight well-named items, a form filled in correctly, a dashboard with round numbers. Real use starts elsewhere. A new user sees the empty state first. A slow connection shows the loading state for seconds. A typo shows the validation error.

Code generated by an AI agent has the same bias, only faster. Ask for “a projects page” and you get the filled version; the empty list, the failed request and the 200-character project name are left to chance. Listing the states up front turns them into requirements, for a designer or for an agent.

The checklist

State What to check Example
Ideal Typical data, realistic amounts, real labels Eight projects with varied names
Empty, first use Explains what goes here and offers the first action “No projects yet” with a Create project button
Empty, no results Says why nothing matches and how to widen the search The query repeated, with a Clear filters button
Empty, cleared The user removed or finished everything “All tasks done”
Loading, initial Layout stays stable, no flash of the empty state Skeleton rows
Loading, action The button shows progress and cannot be sent twice “Saving…” on a disabled button
Partial One item, missing optional fields, missing image A project with no description
Validation error Message next to the field, input kept “Enter a date after today”
Server or network error Says what failed and what to do, with a retry “Could not load projects” and Try again
Permission denied Explains who can do it, instead of a blank page “Only admins can edit billing”
Not found For deleted items and wrong links “This project was deleted”
Success Confirms and shows the next step A toast with a View project link
Destructive confirmation Names what will be lost “Delete 3 files? This cannot be undone.”
Overflow Long names, long translations, large numbers A 60-character title, 1,284,000
Many items Pagination, a virtual list, or Show more 2,000 rows
Session expired The user signs in again and comes back to the same page Return to the invoice after sign-in

Not every screen needs every row. A settings page may have no “many items” state; a read-only report may have no validation error. The value is in deciding that on purpose.

Empty states: three kinds, three messages

“Empty” hides three different situations, and each needs its own copy.

  • First use: nothing exists yet. Explain the value in one sentence and give the one action that fills the screen. An illustration is optional; the action is not.
  • No results: something exists, but the search or filter excludes it. Repeat the query, suggest a fix, offer to clear the filters.
  • Cleared: the user finished or deleted everything. This is often a success, and the screen can say so.

If the three share one generic message (“Nothing here”), users on first use do not know what to do, and users with a typo in their search think their data is gone.

Loading, error and success: timing and recovery

Loading. For content, prefer a skeleton shaped like the final layout, so the page does not jump when the data arrives. For an action, change the button label (“Saving…”) and disable the button until the request ends, which also prevents double submissions. Avoid showing the empty state while data is still loading: users read “No projects” as a fact.

Errors. A useful error message says what happened, in plain words, and what the user can do next. Keep everything the user typed. Put validation messages next to the field they concern, with a summary at the top of long forms.

Success. Confirm what happened and point to the next step. A toast that disappears after a few seconds is fine for small actions; a newly created object deserves a link to it.

Status and error messages also need to reach people who use screen readers. ARIA live regions, and the status and alert roles, announce content that changes without a page load: MDN’s guide to ARIA live regions explains when to use each.

Edge cases that break layouts

These are less separate states than data that stresses every state:

  • Long text: names, titles and email addresses at the maximum length your database allows.
  • Translations: many languages need more room than English for the same label.
  • Numbers: zero, one and many (plurals), negative values, very large amounts.
  • Missing media: an avatar or cover image that failed to load or was never set.
  • Small screens and large text: the layout at phone width, and with the browser text size increased.

A quick test: ask for the ideal state again, filled with the longest realistic values, and see what wraps, truncates or overflows.

Drafting every state with a coding agent

A coding agent is good at producing states once you name them. For a new screen, give it the list; for an existing screen, ask it to read the code first:

Read the Projects page and the components it uses. List every state it can
render, using this checklist: ideal, empty (first use, no results), loading,
partial, validation error, network error, permission denied, success,
overflow. For each state, say whether the code handles it today.
Then draw each state as a separate static HTML file, with realistic data
and our real labels. Do not change the app code.

The “does the code handle it today” column is the useful part: it gives you a list of gaps to design before implementation. When the app already runs, you can also capture each state from the real app; screenshotting every screen with Playwright shows how to reach modals and error states with scripted steps.

Reviewing states side by side in agentappbuilder

agentappbuilder treats the state as the unit of review. Each frame on its canvas is one state of one screen, and the states of a screen sit side by side, so the empty, loading and error versions are visible next to the ideal one. The rules your agent follows tell it to create one frame per state (empty, filled, modal open, error), with real texts and realistic sample data. Frames are static HTML rendered without scripts, so a loading state is drawn as its own frame rather than hidden behind a timer, which is exactly what a checklist review needs.

To add a missing state, ask your agent in your chat, for example: “Prototype the network error state of the Projects screen, with a Try again button.” The tips in working with your agent suggest asking for the states you care about, and the architecture page explains why states are first-class in the product. For the arrows between states, see user flow diagrams that show every screen state.

Use the checklist twice

Run the checklist twice: once when you design, to decide which states exist, and once when you review the built screen, to confirm that each one was implemented as drawn. A state that exists only in the prototype is a bug report waiting to happen; a state that exists only in the code was designed by accident. The review side is covered in how to review UI changes made by an AI agent.

Frequently asked questions

What are the basic UI states every screen needs?

At minimum: the ideal state with typical data, an empty state, a loading state, an error state and a success or confirmation state. Most screens also need a partial state (one item, missing fields) and edge cases such as very long text.

What is the difference between an empty state and a no results state?

An empty state appears when nothing exists yet, for example on first use, and should explain how to add the first item. A no results state appears when a search or filter matches nothing, and should help the user change the query or clear the filters.

Should a loading state use a spinner or a skeleton?

A skeleton shaped like the final layout suits content that takes a moment to load, because the page does not jump when the data arrives. A spinner or a pending label suits a short action, such as a button that is saving.

Try it on your own app

Tell Claude Code one sentence. It creates the project and gives you a link to see your screens.

Tell Claude Code:

Connect this project to agentappbuilder.com and show me its screens.