Free guideEditorial review in progress; your agent sees whether each guide's current version is reviewed. What “reviewed” means

Empty states: first-use, cleared, filtered-empty and error variants

Never leave a region blank: distinguish first-use (explain + create action), user-cleared (confirm success), filtered/no-results (show criteria + clear), and error (what failed + retry) empty states, each with one primary action.

Discipline
Web apps
Type
Pattern
Platforms
Web app, Desktop, Website
Version
1.1.1 · 2026-09-26

Overview

What: What a list, panel or page shows when it has no content to display.

Why: Blank areas make users wonder whether content is loading, broken or filtered. Empty states are also the most natural teaching moment: they appear exactly when the user is looking at a feature they haven't used yet.

Use when: Every list, table, search result, dashboard widget and detail panel that can have zero items.

Do not use when: Content is still loading — show a loading state instead. Never flash an empty state before data arrives; that falsely tells users they have nothing.

Implementation

  1. Pick the variant:
VariantTriggerContentPrimary action
First useFeature never usedWhat this area holds and why it matters (1–2 sentences)Create/connect ("Create a project")
User-clearedAll items completed/archivedPositive confirmation ("No pending proposals")None, or a link to history
No resultsSearch/filter matches nothingEcho the query/filters; suggestions"Clear filters" / edit search
ErrorLoad failedWhat failed, whether data is safe"Try again" + status/help link
No permissionUser lacks accessWho can grant access"Request access" or owner contact
  1. Structure (Blankslate-style): optional small illustration or icon (neutral alert icon for errors), heading (≤8 words), one or two sentences, one primary button, optional secondary text link ("Learn how projects work").
  2. Don't disguise failures as emptiness: if the fetch failed, render the error variant, not "No items yet".
  3. Size: in a full page, center within the content column with max-width ~480px; in a small widget, use a compact inline version (icon + sentence + link).
  4. Offer sample content when learning is hard without data ("Explore with the sample project"), labeled as sample and removable.
  5. Write in the product's vocabulary: name the object and its value, not the mechanism.
  6. Heading level fits the page outline; icons are aria-hidden.

Make the empty case a type error, not a silent gap. Give every list/table view a required status so a call site cannot forget to design the empty case:

type EmptyStateProps = { status: "no-data" | "no-results" | "error"; title: string; description?: string;
  action?: { label: string; onClick: () => void }; secondaryAction?: { label: string; onClick: () => void } };
function EmptyState({ status, title, description, action, secondaryAction }: EmptyStateProps) {
  return (<div role="status" className="flex flex-col items-center gap-3 py-16 text-center">
    <StatusIcon status={status} aria-hidden="true" /><h3>{title}</h3>{description && <p>{description}</p>}
    <div className="flex gap-2">{action && <Button onClick={action.onClick}>{action.label}</Button>}
      {secondaryAction && <Button variant="outline" onClick={secondaryAction.onClick}>{secondaryAction.label}</Button>}</div></div>);
}
// <EmptyState status="no-data" title="No alerts yet" description="Alerts notify you when a metric crosses a threshold you set."
//   action={{ label: "Create your first alert", onClick: openDialog }} secondaryAction={{ label: "Load sample alerts", onClick: loadDemo }} />

role="status" tells assistive technology this is informational, not an error dialog. Model the view's data as a discriminated union (idle | loading | error | empty | ready) so the empty branch is exhaustive-checked by the compiler.

Verification

  • Each list/table has fixtures for first-use, no-results, and error empty states, and they render differently.
  • No-results state names the active query/filters and offers "Clear filters".
  • Error state never says "No items" and offers retry.
  • Empty state is not shown while loading (throttle network; skeleton appears first).
  • Each variant has at most one primary action.
  • Illustrations are decorative (aria-hidden/empty alt) and not required to understand the message.
  • Every list/table component requires an explicit empty-state status prop or union branch (compile-time check).

Sources:

Limitations

  • Illustrations add weight and localization cost; in dense admin tools, a text-only empty state is usually better.
  • Sample data can confuse metrics and exports; tag it and exclude it from billing/usage counts.
  • For permission cases in multi-tenant apps, revealing that a resource exists may leak information; use a generic not-found where that matters.
  • Values verified 2026-09-26: all 2 numeric values in this item were checked (1 in Chromium lab tests, 1 for consistency with house policy) and confirmed; no corrections were needed.