Skip to the page
Tactile UI

Kit part · Empty states

Error state

What a view shows when loading failed. It is the empty state’s sibling: the same tray, with the outline of what should be there printed on its floor, but the lamp in its title is lit red, the words say in plain language what happened and whether anything was lost, and the first key is Retry, with a way round it beside it if there is one. Pressing Retry holds the key, turns the lamp amber and has a screen reader say so.

Element
<div class="tui-empty tui-error-state">
Needs
kit.css + kit.mjs
Covers
Error state · Load failed
Rules
error-state.rules.md · 6
Finishes
Aluminium · Graphite · Oak · Walnut · Porcelain · Black · Daylight · Night · Paper · Phosphor · E-paper · AMOLED
Volumes
Tactile · Quiet
On this page
  1. Variants
  2. Every state, at once
  3. API
  4. Markup
  5. Accessibility
  6. How it’s built
  7. Rules
  8. Related parts

Seats open in 11 days. Want one email that morning?

Variants

The invoices did not load

The server took too long to answer. Nothing was lost.

Slots · a list

The report would not open

The file may have moved. Check the link, or ask whoever shared it.

A sheet · a file or a report

The chart did not load

The readings are safe. They are just not reachable right now.

A plot · a chart

You are offline

Changes stay on this device until you are back online.

With a way round it

This project no longer exists

It was deleted by its owner on 2 October.

Nothing to retry · the page is gone

The invoices did not load

The server took too long to answer. Nothing was lost.

Retrying · lamp amber

The schedules did not load

Nothing was changed.

Side by side · .tui-empty--row

Every state, at once

Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.

Aluminium

PartSlotsSheetPlotRetryingKey focused
Failed

Did not load

One sentence says what happened.

Would not open

One sentence says what happened.

Chart failed

One sentence says what happened.

Did not load

One sentence says what happened.

Did not load

One sentence says what happened.

Graphite

PartSlotsSheetPlotRetryingKey focused
Failed

Did not load

One sentence says what happened.

Would not open

One sentence says what happened.

Chart failed

One sentence says what happened.

Did not load

One sentence says what happened.

Did not load

One sentence says what happened.

API

NameKindValuesWhat it does
.tui-empty.tui-error-stateclasson <div>The empty state’s tray with the error’s changes on it. Use both classes; it follows every finish and both volumes as the empty state does.
.tui-empty__outlineclassaria-hidden="true"The outline of what failed to load: slots, a sheet (--sheet) or a plot (--plot), as in the empty state. Leave it out if there is nothing to draw.
h2.tui-status.tui-error-state__title > .tui-lamp[data-lamp="red"][data-on]elementthe titleWhat failed, in plain words, with the red lamp lit. Use the heading level that fits the page.
.tui-empty__textclasson <p>What happened and whether anything is lost. No codes, no blame, one or two short sentences.
.tui-error-state__detailclassoptional, on <p>Small print for something a person may need to quote, such as a reference.
button[data-error-retry]elementthe first keyRetry. A press holds the key (aria-disabled, focus stays), changes its words to “Retrying…”, turns the lamp amber and fires tui-error-retry.
.tui-error-state__said[role="status"]elementempty, in the markupThe polite region that says “Retrying” and, afterwards, what you pass to setRetrying().
.tui-error-state__actionsclassthe keysRetry, and perhaps one flat key beside it for a way round: a status page, working offline.
setRetrying(tray, on, said?)functionneeds kit.mjsHolds or releases the key from a script. Releasing puts its words back and says what you pass.
retryWords(label)functionpureThe words on a held key: “Retry” gives “Retrying…”, “Try again” gives “Trying again…”.
tui-error-retryeventbubblesFired on the tray when Retry is pressed. The page does the work and replaces the tray or releases the key.
roleattribute"alert" only mid-taskAdd it when the failure appears after the person did something. None for a view that fails on load.

Markup

<!-- The empty state's tray. Name the failure; role="alert" only if it appeared after an action. -->
<div class="tui-empty tui-error-state">
  <div class="tui-empty__outline" aria-hidden="true"><i></i><i></i><i></i></div>
  <h2 class="tui-status tui-error-state__title"><span class="tui-lamp" data-lamp="red" data-on aria-hidden="true"></span>The invoices did not load</h2>
  <p class="tui-empty__text">The server took too long to answer. Nothing was lost.</p>
  <span class="tui-error-state__said" role="status"></span>
  <div class="tui-error-state__actions">
    <button class="tui-key tui-key--primary" type="button" data-error-retry>Retry</button>
    <a class="tui-key tui-key--flat" href="/status">Check the status page</a>
  </div>
</div>
import { setRetrying } from '/kit/kit.mjs';   // wires every [data-error-retry]

tray.addEventListener('tui-error-retry', async () => {
  // The key is already held and the lamp amber.
  try { show(await load()); }                                  // success: replace the tray with the view
  catch { setRetrying(tray, false, 'Still not loading.'); }     // failure: put the key back, say so
});

Needs kit.css and kit.mjs. How to install the kit.

Accessibility

  • The title is a heading, so a screen reader user can find what failed from the heading list. The words say what happened; the red lamp is hidden from a screen reader and is only a second sign.
  • Use role="alert" only when the failure appears after an action, such as a save, so it interrupts. A view that fails on load is simply read in its place.
  • Tab reaches Retry and Enter or Space presses it. Retry keeps the focus. The key is aria-disabled, not disabled, while it works, so the person is not thrown out of it, and the polite status region says “Retrying” and, if it fails again, what you tell it to.
  • The key says what it does: “Retry”, or “Check again” when the cause is the connection. A way round is a link or a flat key with its own words, never a bare “Learn more”.
  • The lamp turns amber and blinks while retrying; the blink stops under reduced motion and the lamp stays lit amber. Keys are 44px on a phone and the tray never scrolls sideways.

How it’s built

No new tray. It is .tui-empty with a lit lamp and an added row for the keys, so the recess, the printed outline and the way each finish draws them are the empty state’s own. The held key is the kit’s aria-disabled key with its words swapped by about thirty lines of script, and the lamp turns amber because the tray says aria-busy, which is also what a screen reader hears.

Rules

error-state.rules.mdIn the brain

Say what failed in plain words, say whether anything is lost, and give the one key that tries again.

6 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.

No circuits yet

Empty state

What a view shows before it has anything: an empty tray with the outline of what goes in it printed on its floor, one sentence and one key.

Check

Disk 82% full.

Alert

A message let into the surface, with an annunciator: a small lit legend (Note, Done, Check, Fault) beside the words that say what happened.

Key

Every button, and every link that acts like one: a cap on a skirt that drops below the plate when pressed.