Navigation

v0.0.4
Application blocks

Empty state

What a view shows before it has anything, and how to begin.

An empty state is what a view shows before it has anything to show. It is the smallest block: the empty component with the right words in it. The words are the work. A good empty state says what belongs here, why it is empty, and what to do next.

Empty state

<section class="sheet container-inline" aria-labelledby="es-title">  <div class="empty">    <div class="empty-media">      <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">        <path d="M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2" />      </svg>    </div>    <h2 class="empty-title" id="es-title">No projects yet</h2>    <p class="empty-description">A project connects a repository to an address. Create one, and every push becomes a deployment.</p>    <div class="empty-actions">      <a class="btn btn-sm" href="#">Read the guide</a>      <button type="button" class="btn btn-sm btn-primary">        <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">          <path d="M12 5v14M5 12h14" />        </svg>New project</button>    </div>  </div></section>

Blocks are markup to copy. They take the page's own text color and size; the previews set fg-text-body text-sm on the body. Each block is a size container, so it reflows by its own width: in a wide page, a sidebar's worth of room or a dialog.

#Four kinds of empty

A view can be empty for four different reasons, and each wants different words.

KindSayOffer
Nothing yetWhat goes here and what it is forThe action that creates the first one
First runThe few steps to a first resultThe next step
No resultsWhat was searched, and which filters still applyA way to widen the search
Something failedWhat happened, in plain words, and whose side it is onA way to try again, in an alert

The first is above. The other three follow.

#First run

For a product a person has just opened, replace the empty view with the way in: steps, set vertically with a sentence each, and the next step as the primary button. The step already done shows as done; aria-current="step" marks where they are.

First run

<section class="sheet container-inline flex flex-col gap-lg p-xl max-w(560) mx-auto" aria-labelledby="es-steps-title">  <header class="flex flex-col gap-xs">    <h2 class="heading heading-lg" id="es-steps-title">Deploy your first project</h2>    <p class="m(0) leading-md">Three steps, about two minutes. You can stop after any of them.</p>  </header>  <ol class="steps steps-vertical">    <li class="steps-item">      <div class="steps-body">        <span class="steps-title">Connect a repository</span>        <span class="steps-description">Signed in with GitHub as ada.</span>      </div>    </li>    <li class="steps-item" aria-current="step">      <div class="steps-body">        <span class="steps-title">Choose what to build</span>        <span class="steps-description">Pick a repository and a branch. We detect the framework.</span>      </div>    </li>    <li class="steps-item">      <div class="steps-body">        <span class="steps-title">Go live</span>        <span class="steps-description">Your site gets an address in under a minute.</span>      </div>    </li>  </ol>  <div class="flex flex-wrap gap-xs">    <button type="button" class="btn btn-primary">Choose a repository</button>    <button type="button" class="btn btn-quiet">Deploy an example instead</button>  </div></section>

#No results

When a search or a filter leaves nothing, repeat the query back, typo and all, and say which filters are still on. A reader who cannot see why the list is empty will assume the data is gone.

No results

<section class="sheet container-inline" aria-live="polite" aria-labelledby="es-none-title">  <div class="empty">    <div class="empty-media">      <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">        <path d="M4 11a7 7 0 1 0 14 0a7 7 0 0 0-14 0M20 20l-4-4" />      </svg>    </div>    <h2 class="empty-title" id="es-none-title">No projects match “drfit”</h2>    <p class="empty-description">Check the spelling, or search all workspaces. Filters are still applied: Ready, Tokyo.</p>    <div class="empty-actions">      <button type="button" class="btn btn-sm">Clear filters</button>      <button type="button" class="btn btn-sm">Search all workspaces</button>    </div>  </div></section>

The region is aria-live="polite", so the change from results to none is announced after the reader stops typing.

#Something failed

A failure is not an empty state, though it stands in the same place. It is an alert: the status hue and an icon say that something is wrong, the words say what, and one button is the way forward. Say that the reader's work is safe when it is. The section keeps the name of the view that failed, so the landmark is still there to find.

Something failed

<section class="container-inline" aria-label="Projects">  <div class="alert alert-danger" role="alert">    <svg class="icon alert-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">      <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0-18 0M12 8v4.5M12 16h.01" />    </svg>    <div class="alert-body">      <p class="alert-title">We could not load your projects</p>      <p class="alert-description">The request timed out. Your projects are safe; this is on our side.        <a class="link" href="#">Check the status page</a>.</p>    </div>    <button type="button" class="btn btn-sm">Try again</button>  </div></section>

#Accessibility

  • The title is a heading at the level of the view it replaces.
  • An empty state that appears in response to an action is announced: aria-live="polite" for no results, role="alert" for a failure.
  • The icon is decoration. Never rely on it, or on its color, to say which kind of empty this is.
  • "Read the guide" goes somewhere, so it is a link drawn as a button; "New project" does something, so it is a button.
  • Keep the primary action the same one the full view offers, so the reader learns it once.