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.
Kit part · Empty states
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.
Seats open in 11 days. Want one email that morning?
The server took too long to answer. Nothing was lost.
The file may have moved. Check the link, or ask whoever shared it.
The readings are safe. They are just not reachable right now.
The server took too long to answer. Nothing was lost.
Nothing was changed.
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
| Part | Slots | Sheet | Plot | Retrying | Key focused |
|---|---|---|---|---|---|
| Failed | Did not loadOne sentence says what happened. | Would not openOne sentence says what happened. | Chart failedOne sentence says what happened. | Did not loadOne sentence says what happened. | Did not loadOne sentence says what happened. |
Graphite
| Part | Slots | Sheet | Plot | Retrying | Key focused |
|---|---|---|---|---|---|
| Failed | Did not loadOne sentence says what happened. | Would not openOne sentence says what happened. | Chart failedOne sentence says what happened. | Did not loadOne sentence says what happened. | Did not loadOne sentence says what happened. |
| Name | Kind | Values | What it does |
|---|---|---|---|
| .tui-empty.tui-error-state | class | on <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__outline | class | aria-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] | element | the title | What failed, in plain words, with the red lamp lit. Use the heading level that fits the page. |
| .tui-empty__text | class | on <p> | What happened and whether anything is lost. No codes, no blame, one or two short sentences. |
| .tui-error-state__detail | class | optional, on <p> | Small print for something a person may need to quote, such as a reference. |
| button[data-error-retry] | element | the first key | Retry. 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"] | element | empty, in the markup | The polite region that says “Retrying” and, afterwards, what you pass to setRetrying(). |
| .tui-error-state__actions | class | the keys | Retry, and perhaps one flat key beside it for a way round: a status page, working offline. |
| setRetrying(tray, on, said?) | function | needs kit.mjs | Holds or releases the key from a script. Releasing puts its words back and says what you pass. |
| retryWords(label) | function | pure | The words on a held key: “Retry” gives “Retrying…”, “Try again” gives “Trying again…”. |
| tui-error-retry | event | bubbles | Fired on the tray when Retry is pressed. The page does the work and replaces the tray or releases the key. |
| role | attribute | "alert" only mid-task | Add it when the failure appears after the person did something. None for a view that fails on load. |
<!-- 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.
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.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.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.
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.
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.
Disk 82% full.
A message let into the surface, with an annunciator: a small lit legend (Note, Done, Check, Fault) beside the words that say what happened.
Every button, and every link that acts like one: a cap on a skirt that drops below the plate when pressed.