Loading, empty and error
What the people table shows while it loads, when there is nothing to show, and when the request fails. Each state says what happened and offers one next step.
Loading
A skeleton the shape of the table: header bar and five rows, shimmering. It is announced once as Loading and drawn only while $loading is true; reduced motion stops the shimmer.
Empty
The empty slot of the table. The pot has its lid off. The primary action is the thing that fills the table.
Nobody here yet
No one matches this view. Clear the search, or add the first person.
Error
Shown with $error. Red outline and title, the problem code and detail from the response, one button that refetches. role="alert" announces it.
Could not load people
NETWORK Failed to fetch. Check your connection and try again.
The markup
All three states in one view, as the page wires them.
<xo-view get="listPeople">
<div class="skeleton" xo-if="$loading" role="status" aria-busy="true"><span class="xo-visually-hidden">Loading people</span><div class="sk-head"><i></i>…</div><div class="sk-row">…</div> <!-- five rows --></div>
<xo-table columns="name,email,role" sortable>
<template slot="empty">
<div class="state"><svg class="art" viewBox="-2 -2 68 68" aria-hidden="true"><rect class="m-ink" x="1" y="35" width="12" height="6.5" rx="3.25"/><rect class="m-ink" x="51" y="35" width="12" height="6.5" rx="3.25"/><path class="m-body" d="M12 31.5h40V44a12 12 0 0 1-12 12H24A12 12 0 0 1 12 44Z"/><rect class="m-ink" x="9" y="8" width="48" height="7.5" rx="3.75" transform="rotate(-14 33 12)"/></svg><h3>Nobody here yet</h3><p>No one matches this view. Clear the search, or add the first person.</p><div class="state-actions"><button class="primary" xo-open="#add"><svg class="icon " aria-hidden="true"><use href="#i-plus"/></svg>Add person</button><button>Clear search</button></div></div>
</template>
</xo-table>
<div class="state error" xo-if="$error" role="alert"><svg class="art" viewBox="-2 -2 68 68" aria-hidden="true"><g transform="rotate(-10 32 40)"><rect class="m-ink" x="8" y="22" width="48" height="7.5" rx="3.75"/><rect class="m-ink" x="1" y="35" width="12" height="6.5" rx="3.25"/><rect class="m-ink" x="51" y="35" width="12" height="6.5" rx="3.25"/><path class="m-body" d="M12 31.5h40V44a12 12 0 0 1-12 12H24A12 12 0 0 1 12 44Z"/><path d="M34 31.5l-4 8 6 4-5 9" fill="none" stroke="var(--xo-color-bg)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></g></svg><h3>Could not load people</h3><p><code>{$error.code}</code> {$error.detail}. Check your connection and try again.</p><div class="state-actions"><button class="primary" xo-refresh><svg class="icon " aria-hidden="true"><use href="#i-redo"/></svg>Try again</button></div></div>
</xo-view>