Work in flight
tier 2 — classesThat an agent is busy, and roughly with what: one status pill, a beam on whatever it is working on, shimmer on words it is still deciding. Then, once the work is back, what to make of it — a mark that says it was generated, how sure the agent is, and how much room it has left.
The status pill
.agent-status holds an orb, an .agent-status-label
in the app's words and, if the wait is long enough to be worth counting, an
.agent-status-time. The orb sits concentric with the pill's rounded end at every
height. Put .text-shimmer on the label while the agent is still at it and take it
off when it stops; .agent-status--warn is the one that waits on the reader.
Say what it is doing, not that it is doing something. “Searching
docs.example.com” tells a reader whether to wait; “Working…” does not. Put the
pill in an aria-live="polite" region if a change of label should be announced.
<div class="sedna-col sedna-gap-3" style="align-items: start">
<span class="agent-status"><span class="orb" data-orb="thinking" role="img" aria-label="Thinking"></span><span class="agent-status-label text-shimmer">Thinking</span></span>
<span class="agent-status"><span class="orb" data-orb="searching" role="img" aria-label="Searching"></span><span class="agent-status-label text-shimmer">Searching docs.example.com</span><span class="agent-status-time">0:07</span></span>
<span class="agent-status agent-status--warn"><span class="orb" data-orb="waiting" role="img" aria-label="Waiting"></span><span class="agent-status-label">Waiting for your approval</span></span>
<span class="agent-status"><span class="orb" data-orb="done" role="img" aria-label="Done"></span><span class="agent-status-label">Done in 1:12</span></span>
</div>
Sizes, and a way to stop
.agent-status--sm (24px), .agent-status--lg (44px) and --xl (64px) for where a page waits on the
agent; the bare pill beside a record. --status-h and --status-orb set
any other height. A small ghost icon button last in the pill is inset to match its end —
give long work a way to stop.
<div class="sedna-col sedna-gap-3" style="align-items: start">
<span class="agent-status agent-status--sm"><span class="orb" data-orb="waiting" role="img" aria-label="Waiting"></span><span class="agent-status-label">Waiting for approval</span></span>
<span class="agent-status"><span class="orb" data-orb="planning" role="img" aria-label="Planning"></span><span class="agent-status-label text-shimmer">Planning the change</span></span>
<span class="agent-status agent-status--lg">
<span class="orb" data-orb="working" role="img" aria-label="Working"></span>
<span class="agent-status-label text-shimmer">Rebuilding the search index</span>
<span class="agent-status-time">2:08</span>
<button class="btn btn--sm btn--ghost btn--icon" type="button" aria-label="Stop"><i class="ri-stop-fill"></i></button>
</span>
<span class="agent-status agent-status--xl"><span class="orb" data-orb="analyzing" role="img" aria-label="Analyzing"></span><span class="agent-status-label text-shimmer">Analyzing 214 tickets</span></span>
</div>
The beam
.beam puts an edge in both of the agent's colours round whatever the agent is busy
with: the card it is summarising, the field it is filling, the button that started the work. It
is drawn on the element's own border, so it needs no wrapper, works on an
<input> and inside a card that clips, and keeps the focus ring.
.beam--glow adds a glow round it. Remove the class when the work is done.
The edge holds still, and the orb and the shimmer beside it are what move: a light turning round an element's border is repainted on every frame, and a page of them kept a processor busy for as long as they were shown.
<div class="sedna-row-wrap sedna-gap-3" style="align-items: start">
<div class="card beam" style="width: 340px">
<div class="card-head"><strong>Summarising 214 tickets</strong><span class="badge badge-ai"><i class="ri-sparkling-2-line"></i><span>AI</span></span></div>
<div class="card-body sedna-col sedna-gap-2" aria-busy="true">
<span class="skeleton skeleton--agent skeleton-text" style="width: 94%"></span>
<span class="skeleton skeleton--agent skeleton-text" style="width: 82%"></span>
<span class="skeleton skeleton--agent skeleton-text" style="width: 58%"></span>
</div>
<div class="card-foot card-foot--split">
<span class="agent-status"><span class="orb" data-orb="reading" role="img" aria-label="Reading"></span><span class="agent-status-label text-shimmer">Reading the tickets</span><span class="agent-status-time">0:09</span></span>
<button class="btn btn--sm btn--ghost" type="button">Cancel</button>
</div>
</div>
<div class="sedna-col sedna-gap-3" style="width: 300px">
<div class="form-field">
<label class="form-label" for="beam-refine">Refine the summary</label>
<input class="form-input beam beam--glow" id="beam-refine" value="Group the tickets by region" />
<span class="form-hint">Click into the field: the focus edge and ring stay under the beam.</span>
</div>
<div class="sedna-row sedna-gap-2">
<button class="btn beam" type="button"><i class="ri-sparkling-2-line"></i><span>Drafting reply</span></button>
<button class="btn btn--ghost" type="button">Stop</button>
</div>
</div>
</div>
Shimmer and placeholders
.text-shimmer is words still being decided: a light passing through the text, in the
text's own colour. .skeleton--agent is the agent's version of a
skeleton — the same shapes, warmed by the agent colours, for an
answer that is being written rather than fetched. Mark the region aria-busy as any
skeleton.
Looking for the lock that held the orders table
<div class="sedna-col sedna-gap-3">
<p style="margin: 0"><span class="text-shimmer">Looking for the lock that held the orders table</span></p>
<div class="card" style="max-width: 420px">
<div class="card-body sedna-col sedna-gap-2" aria-busy="true">
<span class="skeleton skeleton--agent skeleton-text" style="width: 92%"></span>
<span class="skeleton skeleton--agent skeleton-text" style="width: 76%"></span>
<span class="skeleton skeleton--agent skeleton-text" style="width: 84%"></span>
</div>
</div>
</div>
What came back
.badge-ai marks content an agent generated, beside a person's in the same list.
Write the word; the sparkle is decoration.
Most of the 214 tickets trace back to the 02:14 sync failure on orders-console-01. 31 are duplicates of the same report.
<div class="card" style="max-width: 460px">
<div class="card-head"><strong>Ticket summary</strong><span class="badge badge-ai"><i class="ri-sparkling-2-line"></i><span>AI-generated</span></span></div>
<div class="card-body">
<p style="margin: 0">Most of the 214 tickets trace back to the 02:14 sync failure on <code>orders-console-01</code>. 31 are duplicates of the same report.</p>
</div>
<div class="card-foot card-foot--split">
<span class="confidence" data-level="3"><span class="confidence-bars" aria-hidden="true"><i></i><i></i><i></i></span><span>High confidence</span></span>
<button class="btn btn--sm btn--ghost" type="button"><i class="ri-refresh-line"></i><span>Regenerate</span></button>
</div>
</div>
Confidence
.confidence with data-level 1, 2 or 3 fills that many bars — go when
high, info in the middle, warn when low. The words carry it: the bars are
aria-hidden, and a low score says what to do about it.
<div class="sedna-col sedna-gap-2">
<span class="confidence" data-level="3"><span class="confidence-bars" aria-hidden="true"><i></i><i></i><i></i></span><span>High confidence</span></span>
<span class="confidence" data-level="2"><span class="confidence-bars" aria-hidden="true"><i></i><i></i><i></i></span><span>Medium confidence</span></span>
<span class="confidence" data-level="1"><span class="confidence-bars" aria-hidden="true"><i></i><i></i><i></i></span><span>Low confidence · check the sources</span></span>
</div>
The context ring
.context-ring is how much of something is used, as a ring filled to
--value (0 to 100) — an agent's context window, a quota. --warn and
--danger when it is nearly full, .context-ring--lg beside a figure and .context-ring--sm inside a line of text. It is a
role="meter", with the value written again in aria-valuenow.
<div class="sedna-row-wrap sedna-gap-3">
<div class="sedna-row sedna-gap-1">
<span class="context-ring context-ring--sm" style="--value: 38" role="meter" aria-valuenow="38" aria-valuemin="0" aria-valuemax="100" aria-label="Context used"></span>
<span class="text-muted text-sm text-nums">38%</span>
</div>
<div class="sedna-row sedna-gap-2">
<span class="context-ring" style="--value: 38" role="meter" aria-valuenow="38" aria-valuemin="0" aria-valuemax="100" aria-label="Context used"></span>
<span class="text-muted text-sm text-nums">76k / 200k</span>
</div>
<div class="sedna-col sedna-center sedna-gap-1">
<span class="context-ring context-ring--lg" style="--value: 38" role="meter" aria-valuenow="38" aria-valuemin="0" aria-valuemax="100" aria-label="Context used"></span>
<span class="text-sm text-nums">38%</span>
</div>
<div class="sedna-col sedna-center sedna-gap-1">
<span class="context-ring context-ring--lg context-ring--warn" style="--value: 81" role="meter" aria-valuenow="81" aria-valuemin="0" aria-valuemax="100" aria-label="Context used"></span>
<span class="text-sm text-nums">81%</span>
</div>
<div class="sedna-col sedna-center sedna-gap-1">
<span class="context-ring context-ring--lg context-ring--danger" style="--value: 96" role="meter" aria-valuenow="96" aria-valuemin="0" aria-valuemax="100" aria-label="Context used"></span>
<span class="text-sm text-nums">96%</span>
</div>
</div>