The moment a user opens a screen and finds nothing: a brand-new feature, a filter that excluded everything, or an inbox they just cleared. Empty states are teaching surfaces, not failure modes.
When to use it
Empty means the product knows there is nothing to show. It is not a loading state, an error state, or a permissions message.
Use an empty state when
The surface is genuinely emptyThere are no records, tasks, files, messages, vendors, or results to show for the current view.
The user can recover or move forwardA next action exists: create the first item, import content, clear filters, change the query, or restore context.
The absence needs interpretationThe user might wonder whether the product is broken, whether their action succeeded, or what would normally live here.
Use something else when
Data is still loadingUse a loading or skeleton state while retrieval is in progress. Do not show an empty state until the system knows there is nothing to display.
The system failedUse an error state or Alert when the product could not retrieve data. Empty means absence, not failure.
The user lacks accessUse an authorization or permissions message when content exists but the user cannot view it.
Anatomy
Five named parts. The headline and body are non-negotiable; actions depend on the type of empty state.
Visual anchor
Required
An icon or illustration that names the surface, such as an inbox, folder, or filter. Decorative only; the text must carry the meaning.
Use an existing Icon and mark it aria-hidden.
Headline
Required
One short line that says what state the user is looking at. Use "No vendors yet," not "No data."
Name the missing object in the user's vocabulary.
Body
Required
One or two sentences that explain what would live here once it exists and how it gets there.
Keep the body instructional, not promotional.
Primary action
Conditional
Required for first-run states. For no-results, the primary action is usually "Clear filters" or the nearest equivalent.
Use a verb-object label the user recognizes.
Secondary affordance
Optional
A link to documentation, a sample, or a way to switch views. Only include it when it changes what a user would do next.
Do not add a secondary link just to fill space.
Variants
Pick the type first. A first-run surface, a failed filter, and an emptied inbox all look similar, but they are solving different user questions.
First-run
The user has never created or received anything here.
Trigger: A new account, a new feature, or a new tab the user is opening for the first time.
Job: Teach what would live here, then make the first action obvious.
No-results
The user's filter, search, or query returned nothing.
Trigger: A search box with no hits, a filter that excludes everything, or a date range with no entries.
Job: Acknowledge the query, suggest how to broaden it, and give a way back to the full view.
Absent
The user had things here and now they do not.
Trigger: Everything was archived, deleted, completed, or moved.
Job: Confirm what happened and how to recover or restore if relevant.
Examples
Render the same anatomy against different product contexts, then review the copy against the wrong/right pairs.
Vendor watchlist
No vendors on your watchlist yet
Add vendors you want to track. You will see their status, insurance, and recent jobs here.
Vendor search
Nothing matched "acme corp"
Try a shorter query, check the spelling, or clear filters to see all vendors.
Completed approvals
No completed approvals
Approvals you finish will appear here for 90 days. Open requests stay in the Pending tab.
Vendor watchlist, first-run
Wrong
No data
There are no items to display.
Right
No vendors on your watchlist yet
Add vendors you want to track. You will see their status, insurance, and recent jobs here.
Add a vendor
"No data" treats the user as a database. The right version names what would be here, why it matters, and gives the first action.
Search returned nothing
Wrong
No results found
Your search did not match any records.
Right
Nothing matched "acme corp"
Try a shorter query, check the spelling, or clear filters to see all vendors.
Clear filters
The right version echoes the query so the user knows the search ran, names two concrete ways to broaden it, and offers the escape hatch.
Voice and content
Empty states are where Voice & Tone meets product context. Four rules carry most of the weight.
Name what would be here
The headline says what kind of content the surface holds. "No vendors yet" works because the user knows what a vendor is in this app. "No data" works for nobody.
Teach in the body, do not lecture
Explain what the surface is for in one or two sentences. Skip apologies, marketing language, and motivational filler.
Make the primary action recognizable
"Add a vendor" beats "Get started." Lead with the object the user is working with. For no-results, "Clear filters" beats "Reset."
Do not blame the user
A failed filter is not a user error. "Nothing matched" beats "Your search returned no results." Stay neutral and offer the path forward.
Accessibility
Empty states are heard as well as seen. The icon is decorative; the structure carries the meaning.
Heading structure
The headline is a real heading at the right level for the surrounding page, usually H2 or H3. Do not use a styled paragraph and skip the semantic.
Decorative visual anchor
The icon or illustration carries no information by itself. Use aria-hidden so screen readers skip it; the headline and body must stand alone.
Focus order
When an empty state replaces a populated view, the primary action should be the next focusable element after the surface heading. Do not force focus into the empty state on render.
Live regions for async retrieval
For no-results after search or filtering, announce the changed result state with a polite live region. Do not use role="alert" unless the absence is urgent.
Implementation notes
The pattern composes existing primitives. A coding agent should reuse the system pieces below before introducing anything new.
Compose existing primitives
An empty state is a composition of Icon, a semantic heading, paragraph text, and Button or Link for actions. No new primitive ships with this pattern.
For surfaces that already use Panel, keep the empty state inside the same panel. For full-page empties, no extra panel is needed because the page layout already provides the frame.