Workflow
tier 2 — classesA run through a process, drawn as a diagram: what has happened, what is happening now, what comes next, and which way each decision went. Every node is markup the app writes, so a node can carry anything else in the library — an orb, a confidence, a progress bar, the caller's words. The wires between them are drawn from the structure and take their state from the step they lead into, so the app writes one attribute per step and nothing at all on a wire. No script.
A run
ol.workflow is the run, each li.workflow-step one step holding a
.workflow-node, and an li.workflow-fork a place where the run splits into
.workflow-branches, each with its own ol.workflow-path. The structure is
the diagram: the list a screen reader walks is the same list the wires are drawn from.
The trail is the story. Wires behind the step at work are solid go, the wire into it
carries a moving light, and the ones ahead are quiet — so a reader sees where the run has been
and where it is without reading a node. A diagram wider than its container scrolls, so it takes
tabindex="0" for the keyboard, and data-follow keeps the step at work in
view: the diagram scrolls to it as states change, lets go when the reader scrolls away, and takes
up again when they scroll back. A data-workflow-follow button brings the step back
and follows again — the diagram its aria-controls names.
Ticket created Assess severity P1, sure
Categorise Network › Store link, fairly sure
Find related - 2 matches
Link the pattern Stores 9 and 21 reported the same in the last 15 minutes.
Decide where it goes Weighing the on-call rota against the outage pattern
- Urgent
Page on call
Can waitQueue for the morning
Update the ticket - Handed over
<div class="card">
<div class="card-head">
<strong>T-48213 · Card terminals down at store 14</strong>
<span class="agent-status"><span class="orb" data-orb="thinking" role="img" aria-label="Thinking"></span><span class="agent-status-label text-shimmer">Deciding where it goes</span><span class="agent-status-time">0:04</span></span>
<button class="btn btn--sm btn--ghost" type="button" data-workflow-follow aria-controls="run-48213"><i class="ri-focus-3-line"></i> <span>Step at work</span></button>
</div>
<ol class="workflow workflow--grid" id="run-48213" tabindex="0" data-follow aria-label="Ticket T-48213, from the call to the engineer on call">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span>
<span class="workflow-node-title">Ticket created</span>
<span class="workflow-node-meta">By the voice agent · 09:41 <span class="visually-hidden">Done.</span></span>
</header>
</article>
</li>
<li class="workflow-fork">
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-scales-3-line"></i></span>
<span class="workflow-node-title">Assess severity</span>
<span class="workflow-node-meta">Agent · 2.1 s <span class="visually-hidden">Done.</span></span>
</header>
<span class="confidence" data-level="3"><span class="confidence-bars"><i></i><i></i><i></i></span><span>P1, sure</span></span>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-price-tag-3-line"></i></span>
<span class="workflow-node-title">Categorise</span>
<span class="workflow-node-meta">Agent · 1.4 s <span class="visually-hidden">Done.</span></span>
</header>
<span class="confidence" data-level="2"><span class="confidence-bars"><i></i><i></i><i></i></span><span>Network › Store link, fairly sure</span></span>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-git-merge-line"></i></span>
<span class="workflow-node-title">Find related</span>
<span class="workflow-node-meta">Search · 0.8 s <span class="visually-hidden">Done.</span></span>
</header>
</article>
</li>
<li class="workflow-step" data-state="done">
<span class="workflow-label">2 matches</span>
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-links-line"></i></span>
<span class="workflow-node-title">Link the pattern</span>
<span class="workflow-node-meta">Agent · 1.9 s <span class="visually-hidden">Done.</span></span>
</header>
<p class="workflow-node-now">Stores 9 and 21 reported the same in the last 15 minutes.</p>
</article>
</li>
</ol>
</div>
</li>
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-route-line"></i></span>
<span class="workflow-node-title">Decide where it goes</span>
<span class="workflow-node-meta">Agent · 0:04 <span class="visually-hidden">Running.</span></span>
</header>
<p class="workflow-node-now text-shimmer">Weighing the on-call rota against the outage pattern</p>
</article>
</li>
<li class="workflow-fork workflow-fork--decision">
<div class="workflow-branch">
<span class="workflow-label">Urgent</span>
<ol class="workflow-path">
<li class="workflow-step" data-state="next">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-danger"><i class="ri-alarm-warning-line"></i></span>
<span class="workflow-node-title">Page on call</span>
<span class="workflow-node-meta">Push to the rota <span class="visually-hidden">Next.</span></span>
</header>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<span class="workflow-label">Can wait</span>
<ol class="workflow-path">
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-3"><i class="ri-inbox-archive-line"></i></span>
<span class="workflow-node-title">Queue for the morning</span>
<span class="workflow-node-meta">Network team</span>
</header>
</article>
</li>
</ol>
</div>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-edit-box-line"></i></span>
<span class="workflow-node-title">Update the ticket</span>
<span class="workflow-node-meta">Priority, category, summary</span>
</header>
</article>
</li>
<li class="workflow-step">
<span class="workflow-end"><i class="ri-flag-line"></i><span>Handed over</span></span>
</li>
</ol>
</div>
The state of a step
data-state on the <li> — done,
waiting, running, failed, next or
skipped, and nothing at all for a step not reached yet. Put it on the step, never the
node: the wire into the step reads it too. waiting is a step that has been reached and
is held up by someone outside the run — a caller answering, a person approving — which is
a different thing to tell a reader from a step still working.
The paint is not the words. A screen reader hears the list, not the tick, so say the
state in the meta line or in a .visually-hidden span, as the first example does.
Done Waiting Running Failed
Next Not reached Skipped
<div class="sedna-col sedna-gap-3">
<ol class="workflow workflow--sm" tabindex="0" aria-label="States of a step that has been reached">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-go"><i class="ri-check-line"></i></span>
<span class="workflow-node-title">Done</span>
<span class="workflow-node-meta">done</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="waiting">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-warn"><i class="ri-user-voice-line"></i></span>
<span class="workflow-node-title">Waiting</span>
<span class="workflow-node-meta">waiting</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="running">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-loader-4-line"></i></span>
<span class="workflow-node-title">Running</span>
<span class="workflow-node-meta">running</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="failed">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-danger"><i class="ri-error-warning-line"></i></span>
<span class="workflow-node-title">Failed</span>
<span class="workflow-node-meta">failed</span>
</header>
</article>
</li>
</ol>
<ol class="workflow workflow--sm" tabindex="0" aria-label="States of a step that has not been reached">
<li class="workflow-step" data-state="next">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon"><i class="ri-arrow-right-line"></i></span>
<span class="workflow-node-title">Next</span>
<span class="workflow-node-meta">next</span>
</header>
</article>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon"><i class="ri-time-line"></i></span>
<span class="workflow-node-title">Not reached</span>
<span class="workflow-node-meta">no data-state</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="skipped">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon"><i class="ri-skip-forward-line"></i></span>
<span class="workflow-node-title">Skipped</span>
<span class="workflow-node-meta">skipped</span>
</header>
</article>
</li>
</ol>
</div>
The step at work
A step at work wears one of three looks, chosen on its node: its edge in the light’s colour
with a ring, by default; .workflow-node--glow, the same edge with a glow; or
.workflow-node--agent, the agent’s two colours and glow, for a step an agent is
doing. Put the class on the node whatever its state — the look shows only while the step is
at work, so an app writes it once, from what the step is, and never from where the run is.
The wires never wear the agent’s colours. What runs along them is data, whichever kind of step sent it.
Look up the store
Notify the store
Decide where it goes
<ol class="workflow workflow--sm" tabindex="0" aria-label="Three steps at work, one in each look">
<li class="workflow-step" data-state="running">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-database-2-line"></i></span>
<span class="workflow-node-title">Look up the store</span>
<span class="workflow-node-meta">Asset database · running</span>
</header>
</article>
</li>
</ol>
<ol class="workflow workflow--sm" tabindex="0" aria-label="A step at work with a glow">
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--glow">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-mail-send-line"></i></span>
<span class="workflow-node-title">Notify the store</span>
<span class="workflow-node-meta">Mail · running</span>
</header>
</article>
</li>
</ol>
<ol class="workflow workflow--sm" tabindex="0" aria-label="An agent's step at work">
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-sparkling-2-line"></i></span>
<span class="workflow-node-title">Decide where it goes</span>
<span class="workflow-node-meta">Agent · running</span>
</header>
</article>
</li>
</ol>
What a node carries
.workflow-node-head is the one fixed part: whatever leads it — a
.workflow-node-icon tile, an .orb, an
.avatar — then .workflow-node-title and
.workflow-node-meta. A .series-* class on the tile colours it, and
.workflow-node-icon--agent paints it in the agent's colours, so the steps an agent
takes stand apart from the ones a tool does.
Everything after the head is the node's body, spaced for you: .workflow-node-now for
what it is doing in a line or two — with .text-shimmer
while the words are still a guess — a .progress, chips, a
.confidence, and .workflow-node-foot for the
small print. Every wire meets the head's centre line, so nodes of any height still join in a
straight line.
Create a ticket Check the runbook No fix on record for “host unreachable” at a single store.
Read the store's link Comparing packet loss with the other stores in the region
12 of 20 stores orders-console-01Write the summary Ticket Call transcript
<ol class="workflow" tabindex="0" aria-label="Four nodes, from the least to the most a node can carry">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span>
<span class="workflow-node-title">Create a ticket</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-book-2-line"></i></span>
<span class="workflow-node-title">Check the runbook</span>
<span class="workflow-node-meta">Knowledge base · 0.6 s</span>
</header>
<p class="workflow-node-now">No fix on record for “host unreachable” at a single store.</p>
</article>
</li>
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="orb" data-orb="analyzing" role="img" aria-label="Analysing"></span>
<span class="workflow-node-title">Read the store's link</span>
<span class="workflow-node-meta">Agent · 0:09</span>
</header>
<p class="workflow-node-now text-shimmer">Comparing packet loss with the other stores in the region</p>
<div class="progress" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" aria-label="Stores compared"><div class="progress-bar" style="width: 60%"></div></div>
<div class="workflow-node-foot">
<span>12 of 20 stores</span>
<span class="sedna-push">orders-console-01</span>
</div>
</article>
</li>
<li class="workflow-step">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-quill-pen-line"></i></span>
<span class="workflow-node-title">Write the summary</span>
<span class="workflow-node-meta">Agent</span>
</header>
<div class="chip-set">
<span class="chip"><span class="chip-label">Ticket</span></span>
<span class="chip"><span class="chip-label">Call transcript</span></span>
</div>
</article>
</li>
</ol>
Steps that run side by side
A .workflow-fork followed by a step joins again: the bracket on the right gathers its
branches into the next step, and a short branch's wire runs on to meet it. Nothing is written on a
bracket. The piece down to each branch lights once that branch has been reached, and the piece
back up once its last step is done, so a reader can see which branch the join is still waiting for.
Ticket created Assess severity
Find related Link the pattern
Categorise
Update the ticket
<ol class="workflow workflow--sm" tabindex="0" aria-label="Triage: three checks run side by side, then the ticket is updated">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span>
<span class="workflow-node-title">Ticket created</span>
<span class="workflow-node-meta">T-48213</span>
</header>
</article>
</li>
<li class="workflow-fork">
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-scales-3-line"></i></span>
<span class="workflow-node-title">Assess severity</span>
<span class="workflow-node-meta">P1 · done</span>
</header>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-git-merge-line"></i></span>
<span class="workflow-node-title">Find related</span>
<span class="workflow-node-meta">2 matches · done</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-links-line"></i></span>
<span class="workflow-node-title">Link the pattern</span>
<span class="workflow-node-meta">Agent · running</span>
</header>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-price-tag-3-line"></i></span>
<span class="workflow-node-title">Categorise</span>
<span class="workflow-node-meta">Store link · done</span>
</header>
</article>
</li>
</ol>
</div>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-edit-box-line"></i></span>
<span class="workflow-node-title">Update the ticket</span>
<span class="workflow-node-meta">Waits for all three</span>
</header>
</article>
</li>
</ol>
A decision
.workflow-fork--decision is a fork where one branch is chosen. Mark it
data-state="taken" and the others data-state="skipped": a skipped branch
goes quiet, dashed and grey, with no state written on any step inside it. A
.workflow-label first in a branch is the case it is for, on its wire.
A fork that ends its path does not join; each branch ends where its last step does. Before the choice is made, leave both branches unmarked.
Fixed on the call? - Yes
Confirm and close
NoOpen a ticket Read it back
<ol class="workflow workflow--sm" tabindex="0" aria-label="The agent could not fix it on the call, so it opened a ticket">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-question-line"></i></span>
<span class="workflow-node-title">Fixed on the call?</span>
<span class="workflow-node-meta">No · still down</span>
</header>
</article>
</li>
<li class="workflow-fork workflow-fork--decision">
<div class="workflow-branch" data-state="skipped">
<span class="workflow-label">Yes</span>
<ol class="workflow-path">
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-go"><i class="ri-chat-check-line"></i></span>
<span class="workflow-node-title">Confirm and close</span>
<span class="workflow-node-meta">Not taken</span>
</header>
</article>
</li>
</ol>
</div>
<div class="workflow-branch" data-state="taken">
<span class="workflow-label">No</span>
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span>
<span class="workflow-node-title">Open a ticket</span>
<span class="workflow-node-meta">T-48213 · done</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-voiceprint-line"></i></span>
<span class="workflow-node-title">Read it back</span>
<span class="workflow-node-meta">Voice agent · speaking</span>
</header>
</article>
</li>
</ol>
</div>
</li>
</ol>
Steps that repeat
li.workflow-loop holds the path that repeats — a turn of a conversation, a retry
— and draws the way back under it. .workflow-loop-count on the way back says how
many times, in your words. data-state on the loop colours the way back, and the steps
inside take their own: show the turn in progress, not every turn so far.
- Call in
Ask Listen Check the runbook
- Fixed, or a ticket
<ol class="workflow workflow--sm" tabindex="0" aria-label="Troubleshooting with the caller, one question at a time">
<li class="workflow-step" data-state="done">
<span class="workflow-end"><i class="ri-phone-line"></i><span>Call in</span></span>
</li>
<li class="workflow-loop" data-state="running">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-question-answer-line"></i></span>
<span class="workflow-node-title">Ask</span>
<span class="workflow-node-meta">“Is the router lit?”</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="waiting">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-warn"><i class="ri-user-voice-line"></i></span>
<span class="workflow-node-title">Listen</span>
<span class="workflow-node-meta">Waiting for the caller</span>
</header>
</article>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-book-2-line"></i></span>
<span class="workflow-node-title">Check the runbook</span>
<span class="workflow-node-meta">Knowledge base</span>
</header>
</article>
</li>
</ol>
<span class="workflow-loop-count"><i class="ri-repeat-line"></i><span>Turn 2</span></span>
</li>
<li class="workflow-step">
<span class="workflow-end"><i class="ri-flag-line"></i><span>Fixed, or a ticket</span></span>
</li>
</ol>
Starts, ends and what was handed on
.workflow-end stands in for a node where a run starts or stops; done, it turns go. A
.workflow-label first in a step is what was passed along the wire into it — a
transcript, a ticket number, three articles — which is often the one thing a reader wants to
know about a hand-off.
- Call ended
- Transcript
Summarise the call - T-48213
Attach articles - 3 articles Ticket ready
<ol class="workflow workflow--sm" tabindex="0" aria-label="What each step handed to the next">
<li class="workflow-step" data-state="done">
<span class="workflow-end"><i class="ri-phone-line"></i><span>Call ended</span></span>
</li>
<li class="workflow-step" data-state="done">
<span class="workflow-label"><i class="ri-chat-voice-line"></i><span>Transcript</span></span>
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-quill-pen-line"></i></span>
<span class="workflow-node-title">Summarise the call</span>
<span class="workflow-node-meta">Agent · 3.0 s</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="done">
<span class="workflow-label">T-48213</span>
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-book-2-line"></i></span>
<span class="workflow-node-title">Attach articles</span>
<span class="workflow-node-meta">Knowledge base</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="done">
<span class="workflow-label">3 articles</span>
<span class="workflow-end"><i class="ri-checkbox-circle-line"></i><span>Ticket ready</span></span>
</li>
</ol>
Top to bottom
.workflow--down runs the diagram down the page for a phone, a tablet held upright or a side
panel. Nodes take the width they are given, and the wire runs down a rail through their icons. A fork
hangs its branches off the rail, indented like a tree, and the rail runs on past them to the next
step; a loop draws its way back up its right-hand side. The markup is the same as across — only
the class differs.
.workflow--auto is across on a wide screen and down below 640px, so one diagram serves a
desk and a phone; the live run’s detail uses it. With
data-follow in a box of fixed height, a diagram run down keeps the step at work in view
by scrolling down instead of across.
- Call in
Identify the caller Ask Look it up
- Fixed
- Confirm and close
Not fixedCreate a ticket
Assess severity
Categorise
- 3 checks
Decide where it goes - Handed over
<div style="max-width: 380px; margin-inline: auto">
<ol class="workflow workflow--down workflow--sm" tabindex="0" aria-label="Card terminals down at store 14, on a phone">
<li class="workflow-step" data-state="done"><span class="workflow-end"><i class="ri-phone-line"></i><span>Call in</span></span></li>
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent"><header class="workflow-node-head"><span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-user-search-line"></i></span><span class="workflow-node-title">Identify the caller</span><span class="workflow-node-meta">Alex Fischer, store 14</span></header></article>
</li>
<li class="workflow-loop" data-state="done">
<ol class="workflow-path">
<li class="workflow-step" data-state="done"><article class="workflow-node workflow-node--agent"><header class="workflow-node-head"><span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-question-answer-line"></i></span><span class="workflow-node-title">Ask</span><span class="workflow-node-meta">Voice agent</span></header></article></li>
<li class="workflow-step" data-state="done"><article class="workflow-node"><header class="workflow-node-head"><span class="workflow-node-icon series-4"><i class="ri-book-2-line"></i></span><span class="workflow-node-title">Look it up</span><span class="workflow-node-meta">Runbook</span></header></article></li>
</ol>
<span class="workflow-loop-count"><i class="ri-repeat-line"></i><span>2</span></span>
</li>
<li class="workflow-fork workflow-fork--decision">
<div class="workflow-branch" data-state="skipped"><span class="workflow-label">Fixed</span><ol class="workflow-path"><li class="workflow-step"><span class="workflow-end"><i class="ri-chat-check-line"></i><span>Confirm and close</span></span></li></ol></div>
<div class="workflow-branch" data-state="taken"><span class="workflow-label">Not fixed</span><ol class="workflow-path">
<li class="workflow-step" data-state="done"><article class="workflow-node"><header class="workflow-node-head"><span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span><span class="workflow-node-title">Create a ticket</span><span class="workflow-node-meta">T-48213</span></header></article></li>
</ol></div>
</li>
<li class="workflow-fork">
<div class="workflow-branch"><ol class="workflow-path"><li class="workflow-step" data-state="done"><article class="workflow-node workflow-node--agent"><header class="workflow-node-head"><span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-scales-3-line"></i></span><span class="workflow-node-title">Assess severity</span><span class="workflow-node-meta">P1</span></header></article></li></ol></div>
<div class="workflow-branch"><ol class="workflow-path"><li class="workflow-step" data-state="running"><article class="workflow-node workflow-node--agent"><header class="workflow-node-head"><span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-price-tag-3-line"></i></span><span class="workflow-node-title">Categorise</span><span class="workflow-node-meta">Agent</span></header></article></li></ol></div>
</li>
<li class="workflow-step" data-state="next">
<span class="workflow-label">3 checks</span>
<article class="workflow-node workflow-node--agent"><header class="workflow-node-head"><span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-route-line"></i></span><span class="workflow-node-title">Decide where it goes</span><span class="workflow-node-meta">Agent</span></header></article>
</li>
<li class="workflow-step"><span class="workflow-end"><i class="ri-flag-line"></i><span>Handed over</span></span></li>
</ol>
</div>
How much moves
One streak of light at a time leaves the step before the one at work and runs the whole way into it
— down a fork’s bracket into every branch at work, up a join’s bracket from every
branch into the step after it — at one speed, round every bend, in one piece. The step at work
is what the reader watches, so the light stays quiet. .workflow--flow-off stills it to
a lit line.
--workflow-flow-speed makes it slower or faster (0.5 is half the pace) and
--workflow-flow-packets sparser or denser at the same pace (2 is twice as
many). Set them on the diagram. The live run has a control for each.
Ticket created Assess severity
Categorise
Update the ticket
Ticket created Assess severity
Categorise
Update the ticket
<ol class="workflow workflow--sm" style="--workflow-flow-speed: 0.5; --workflow-flow-packets: 2" tabindex="0" aria-label="Triage, with the light at half the pace and twice as dense">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span>
<span class="workflow-node-title">Ticket created</span>
<span class="workflow-node-meta">T-48213</span>
</header>
</article>
</li>
<li class="workflow-fork">
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-scales-3-line"></i></span>
<span class="workflow-node-title">Assess severity</span>
<span class="workflow-node-meta">P1 · done</span>
</header>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-price-tag-3-line"></i></span>
<span class="workflow-node-title">Categorise</span>
<span class="workflow-node-meta">Agent · running</span>
</header>
</article>
</li>
</ol>
</div>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-edit-box-line"></i></span>
<span class="workflow-node-title">Update the ticket</span>
<span class="workflow-node-meta">Waits for both</span>
</header>
</article>
</li>
</ol>
<ol class="workflow workflow--sm workflow--flow-off" tabindex="0" aria-label="Triage, with the light still">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span>
<span class="workflow-node-title">Ticket created</span>
<span class="workflow-node-meta">T-48213</span>
</header>
</article>
</li>
<li class="workflow-fork">
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-scales-3-line"></i></span>
<span class="workflow-node-title">Assess severity</span>
<span class="workflow-node-meta">P1 · done</span>
</header>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-price-tag-3-line"></i></span>
<span class="workflow-node-title">Categorise</span>
<span class="workflow-node-meta">Agent · running</span>
</header>
</article>
</li>
</ol>
</div>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-edit-box-line"></i></span>
<span class="workflow-node-title">Update the ticket</span>
<span class="workflow-node-meta">Waits for both</span>
</header>
</article>
</li>
</ol>
An overview
The same classes at another height. A handful of stages, each standing for a diagram of its own, is
how a run reads to someone who will never open a step: .workflow--lg sizes everything
up for a room, and .workflow--fill shares the width out so the overview fits instead of
scrolling. .workflow--sm is the other way, for a diagram in a panel, and
.workflow--xl further still, for a wall screen. A single node can be widened with
--workflow-node on its step.
.workflow--focus is for showing rather than reading: every step keeps only its head
except the one at work, which opens wider with everything in it. Write the detail into every node;
the diagram shows it for the step that is happening. The wall screen is
the two together.
Call Ticket Triage Three stores, one region: an outage
On call
<ol class="workflow workflow--lg workflow--fill" tabindex="0" aria-label="Card terminals down at store 14: where the request is now">
<li class="workflow-step" data-state="done">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-customer-service-2-line"></i></span>
<span class="workflow-node-title">Call</span>
<span class="workflow-node-meta">4:12 with the caller</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-coupon-3-line"></i></span>
<span class="workflow-node-title">Ticket</span>
<span class="workflow-node-meta">T-48213, P1</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="running">
<article class="workflow-node workflow-node--agent">
<header class="workflow-node-head">
<span class="orb" data-orb="thinking" role="img" aria-label="Thinking"></span>
<span class="workflow-node-title">Triage</span>
<span class="workflow-node-meta">Agent · 0:12</span>
</header>
<p class="workflow-node-now text-shimmer">Three stores, one region: an outage</p>
</article>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-danger"><i class="ri-alarm-warning-line"></i></span>
<span class="workflow-node-title">On call</span>
<span class="workflow-node-meta">Rin Nakamura</span>
</header>
</article>
</li>
</ol>
A run that is no agent's
Nothing in a workflow is about agents. A release, a production line, a delivery, an onboarding
— any run of steps with states is drawn the same way. The trail and the light are knobs on the
.workflow: --workflow-trail for the way the run went, and
--workflow-flow, --workflow-flow-line, --workflow-flow-tint and
--workflow-flow-glow for the data flowing into the step at work and that step’s
edge. Set them from tokens, as here in the brand’s colours.
Build Unit tests
Security scan
- v2.14.1
Deploy to staging Production
<ol class="workflow workflow--sm" tabindex="0" aria-label="Release 2.14.1, stage by stage"
style="--workflow-trail: var(--info-solid); --workflow-flow: var(--brand-soft); --workflow-flow-line: var(--brand-tint-strong); --workflow-flow-tint: var(--brand-tint); --workflow-flow-glow: var(--brand-glow)">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-1"><i class="ri-hammer-line"></i></span>
<span class="workflow-node-title">Build</span>
<span class="workflow-node-meta">a3f9c1e · 3:12</span>
</header>
</article>
</li>
<li class="workflow-fork">
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-flask-line"></i></span>
<span class="workflow-node-title">Unit tests</span>
<span class="workflow-node-meta">1,204 passed</span>
</header>
</article>
</li>
</ol>
</div>
<div class="workflow-branch">
<ol class="workflow-path">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-shield-check-line"></i></span>
<span class="workflow-node-title">Security scan</span>
<span class="workflow-node-meta">No findings</span>
</header>
</article>
</li>
</ol>
</div>
</li>
<li class="workflow-step" data-state="running">
<span class="workflow-label">v2.14.1</span>
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-3"><i class="ri-rocket-2-line"></i></span>
<span class="workflow-node-title">Deploy to staging</span>
<span class="workflow-node-meta">12 of 30 smoke tests</span>
</header>
</article>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-3"><i class="ri-earth-line"></i></span>
<span class="workflow-node-title">Production</span>
<span class="workflow-node-meta">Needs approval</span>
</header>
</article>
</li>
</ol>
Why it chose
ol.workflow-decision is the options a step weighed, a .meter
each, the score, and .workflow-decision-why under it. data-state="chosen"
ticks the winner; "rejected" quiets the rest but keeps them readable, because why the
others lost is half of the explanation. Pair it with the .reasoning
behind it.
- Page the on-call engineer (chosen) 0.86 Three stores in one region within 15 minutes, out of hours: an outage, not a fault.
- Queue for the network team 0.31 The team starts at 07:00; the tills would be down for nine hours.
- Close as a known issue 0.08
Thought for 3 s
One store losing its link is a fault for the morning. Three stores in the same region within a quarter of an hour is the regional uplink, and nobody can fix that from a store.
It is 21:40 and the stores close at 22:00, but they open at 07:00 and cannot take cards until the link is back. That is worth waking someone for.
<div class="card" style="max-width: 560px">
<div class="card-head">
<strong>Where the ticket goes</strong>
<span class="badge badge-ai"><i class="ri-sparkling-2-line"></i><span>Decided by the agent</span></span>
</div>
<div class="card-body sedna-col sedna-gap-3">
<ol class="workflow-decision" aria-label="Options the agent weighed">
<li data-state="chosen">
<span class="workflow-decision-option">Page the on-call engineer <span class="visually-hidden">(chosen)</span></span>
<span class="meter"><span class="meter-fill" style="--value: 86%"></span></span>
<span class="workflow-decision-score">0.86</span>
<span class="workflow-decision-why">Three stores in one region within 15 minutes, out of hours: an outage, not a fault.</span>
</li>
<li data-state="rejected">
<span class="workflow-decision-option">Queue for the network team</span>
<span class="meter"><span class="meter-fill" style="--value: 31%"></span></span>
<span class="workflow-decision-score">0.31</span>
<span class="workflow-decision-why">The team starts at 07:00; the tills would be down for nine hours.</span>
</li>
<li data-state="rejected">
<span class="workflow-decision-option">Close as a known issue</span>
<span class="meter"><span class="meter-fill" style="--value: 8%"></span></span>
<span class="workflow-decision-score">0.08</span>
</li>
</ol>
<details class="reasoning">
<summary><i class="ri-arrow-right-s-line reasoning-chevron"></i><span>Thought for 3 s</span></summary>
<div class="reasoning-body">
<p>One store losing its link is a fault for the morning. Three stores in the same region within a quarter of an hour is the regional uplink, and nobody can fix that from a store.</p>
<p>It is 21:40 and the stores close at 22:00, but they open at 07:00 and cannot take cards until the link is back. That is worth waking someone for.</p>
</div>
</details>
</div>
</div>
A short flow, centred
.workflow--center centres a diagram narrower than its container, and still starts it
at the edge once it is wider, so nothing is cut off.
Requested Approval Paid out
<ol class="workflow workflow--center" tabindex="0" aria-label="Refund for ORD-4211: where it is now">
<li class="workflow-step" data-state="done">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-2"><i class="ri-refund-2-line"></i></span>
<span class="workflow-node-title">Requested</span>
<span class="workflow-node-meta">Alex Fischer</span>
</header>
</article>
</li>
<li class="workflow-step" data-state="running">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-3"><i class="ri-scales-3-line"></i></span>
<span class="workflow-node-title">Approval</span>
<span class="workflow-node-meta">Finance</span>
</header>
</article>
</li>
<li class="workflow-step">
<article class="workflow-node">
<header class="workflow-node-head">
<span class="workflow-node-icon series-4"><i class="ri-bank-card-line"></i></span>
<span class="workflow-node-title">Paid out</span>
</header>
</article>
</li>
</ol>
A step and what it did
A node that opens its detail is a <button class="workflow-node"> with spans inside,
and aria-pressed="true" on the one on show. The detail is your own panel beside the
diagram — a .sedna-split stacks it underneath when the room
runs out — holding whatever explains the step: what it read, what it weighed, the tools it ran.
.workflow--grid dots the canvas. For a graph too large to write by hand — a flow generated from an
automation's own definition — the graph draws the same states on a
canvas.
<div class="sedna-split sedna-split--lg">
<ol class="workflow workflow--sm workflow--grid" tabindex="0" aria-label="The ticket's steps; choose one to see what it did">
<li class="workflow-step" data-state="done">
<button class="workflow-node" type="button" aria-pressed="false">
<span class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-scales-3-line"></i></span>
<span class="workflow-node-title">Assess severity</span>
<span class="workflow-node-meta">P1 · 2.1 s</span>
</span>
</button>
</li>
<li class="workflow-step" data-state="done">
<button class="workflow-node" type="button" aria-pressed="true">
<span class="workflow-node-head">
<span class="workflow-node-icon workflow-node-icon--agent"><i class="ri-route-line"></i></span>
<span class="workflow-node-title">Decide where it goes</span>
<span class="workflow-node-meta">Page on call · 3.0 s</span>
</span>
</button>
</li>
<li class="workflow-step" data-state="waiting">
<button class="workflow-node" type="button" aria-pressed="false">
<span class="workflow-node-head">
<span class="workflow-node-icon series-danger"><i class="ri-alarm-warning-line"></i></span>
<span class="workflow-node-title">Page on call</span>
<span class="workflow-node-meta">Waiting for Rin</span>
</span>
</button>
</li>
</ol>
<aside class="card sedna-split-aside">
<div class="card-head">
<strong>Decide where it goes</strong>
<span class="badge badge--go">Done</span>
</div>
<div class="card-body sedna-col sedna-gap-3">
<div>
<div class="kv"><span class="k">Started</span><span class="v">21:40:12</span></div>
<div class="kv"><span class="k">Took</span><span class="v">3.0 s</span></div>
<div class="kv"><span class="k">Read</span><span class="v">T-48213, 2 related</span></div>
</div>
<ol class="workflow-decision" aria-label="Options it weighed">
<li data-state="chosen">
<span class="workflow-decision-option">Page on call <span class="visually-hidden">(chosen)</span></span>
<span class="meter"><span class="meter-fill" style="--value: 86%"></span></span>
<span class="workflow-decision-score">0.86</span>
</li>
<li data-state="rejected">
<span class="workflow-decision-option">Queue for the morning</span>
<span class="meter"><span class="meter-fill" style="--value: 31%"></span></span>
<span class="workflow-decision-score">0.31</span>
</li>
</ol>
<ol class="agent-steps">
<li data-state="done">
<span class="agent-step-icon"><i class="ri-check-line"></i></span>
<details class="agent-step">
<summary><span class="agent-step-label"><i class="ri-calendar-schedule-line"></i><span>Read the on-call rota</span></span><span class="agent-step-meta">0.4 s</span></summary>
<pre class="code-block"><code>rota.current(team: "network") → Rin Nakamura, until 07:00</code></pre>
</details>
</li>
</ol>
</div>
</aside>
</div>