Connection lost. Reconnecting… attempt 1 of 8
Paused. Your work is held on the server.
Could not reconnect.
This session has expired on the server.
An unhandled error has occurred.
Sedna.UI
v0.31.0 · main

Work in flight

tier 2 — classes

That 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.

Thinking Searching docs.example.com0:07 Waiting for your approval Done in 1:12
<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.

Waiting for approval Planning the change Rebuilding the search index 2:08 Analyzing 214 tickets
<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.

Summarising 214 ticketsAI
Reading the tickets0:09
Click into the field: the focus edge and ring stay under the beam.
<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.

Ticket summaryAI-generated

Most of the 214 tickets trace back to the 02:14 sync failure on orders-console-01. 31 are duplicates of the same report.

High confidence
<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.

High confidence Medium confidence Low confidence · check the sources
<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 &middot; 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.

38%
76k / 200k
38%
81%
96%
<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>