Skip to content

Pattern

Empty, error and loading states

What a region shows when there is nothing yet, when something failed, and while it loads.

.b-switcher.b-flow.b-center.b-cluster

Every region that loads data needs all three. Design them with the page, not after. Empty states explain and offer the first action; error states say what happened and how to recover; loading states hold the layout so the page doesn’t jump.

Preview

Acuity Brands Lighting

Each kit renders in its own frame and follows the theme and density set in the header. Open full-size ↗

HTML

Layout uses Beam compositions and utilities only. Buttons, inputs, toggles, badges and tables here are stand-ins so the preview renders — in product, use the Cantina components below.

<div class="[ b-wrapper b-region ]">
  <div class="[ b-switcher ]" data-limit="3">
    <section class="[ b-flow b-center ] [ b-card ]" data-text="center" data-space="sm" aria-label="Empty state">
      <span class="[ b-empty-mark ]" aria-hidden="true"></span>
      <h2 class="[ u-type-h5 ]">No schedules yet</h2>
      <p class="[ u-type-body-sm u-text-neutral-secondary ]">Schedules turn lights on and off automatically.</p>
      <div><button class="[ b-button ]" data-variant="solid" type="button">Create schedule</button></div>
    </section>
    <section class="[ b-flow ] [ b-card ]" data-space="sm" aria-label="Error state">
      <div class="[ b-flow ] [ b-alert ]" data-tone="error" data-space="xs" role="alert">
        <strong class="[ u-type-label ]">Couldn’t load devices</strong>
        <p class="[ u-type-body-sm ]">The gateway didn’t respond. Check its connection, then try again.</p>
      </div>
      <div><button class="[ b-button ]" data-variant="outline" type="button">Retry</button></div>
    </section>
    <section class="[ b-flow ] [ b-card ]" data-space="sm" aria-label="Loading state" aria-busy="true">
      <span class="[ b-skeleton ]" data-size="title"></span>
      <span class="[ b-skeleton ]"></span>
      <span class="[ b-skeleton ]"></span>
      <span class="[ b-skeleton ]" data-size="short"></span>
    </section>
  </div>
</div>

Cantina components

  • alert
  • button
  • snackbar

Open Cantina ↗

Recipe

The rules an agent follows to build this pattern. This is what goes into beam.skill.

  1. Replace the content area, not the page: the shell and page title stay put.
  2. Empty: short heading that says what will be here, one line on how to start, one primary action. No illustrations required.
  3. Error: Cantina <Alert> tone error inside the region — what happened, what to do (Retry). Transient failures use a snackbar instead.
  4. Loading: skeleton blocks shaped like the content (lines, rows) for >300 ms waits; respect reduced motion (no pulse).
  5. Centre empty/error content with .b-center[data-text="center"] inside the region.
beam.skill recipe (Markdown)
## Pattern: Empty, error and loading states
What a region shows when there is nothing yet, when something failed, and while it loads.

Compositions: .b-switcher, .b-flow, .b-center, .b-cluster
Cantina: alert, button, snackbar

1. Replace the content area, not the page: the shell and page title stay put.
2. Empty: short heading that says what will be here, one line on how to start, one primary action. No illustrations required.
3. Error: Cantina <Alert> tone error inside the region — what happened, what to do (Retry). Transient failures use a snackbar instead.
4. Loading: skeleton blocks shaped like the content (lines, rows) for >300 ms waits; respect reduced motion (no pulse).
5. Centre empty/error content with .b-center[data-text="center"] inside the region.