Sequences
layout: sequence reads a diagram on a time axis: participants across the top,
messages down the page in the order you wrote them.
Two lines are a diagram
{ layout: sequence; }
user -> server "login"
server --> user "token"
The links are the messages, and source order is time: the first line written is the first row drawn.
Nothing was declared here either. An endpoint nobody declared creates a
participant, appended in first-use order, so a quick exchange needs no header
block at all. -> is a call, --> a return.
Participants you declare
{ layout: sequence; }
|box#user| "Customer" [ |icon| "user" { fill: none; stroke: --rose-deep; } ]
|box#shop| "Storefront" { fill: --sky-wash; stroke: --sky-deep; }
|cyl#db| "Orders" { fill: --orange-wash; stroke: --orange-deep; }
user -> shop "place order"
shop -> db "reserve stock"
db --> shop "reserved"
shop --> user "order #1024"
Declaring the participants buys three things at once: their left-to-right order, their type, and their paint.
That paint carries down the page. A participant lends its own fill and
stroke to its apparatus — the lifeline and every activation bar — so
colouring a header colours its whole timeline.
An actor is just a box wrapping an |icon|: the name stays the header, and the
glyph becomes the picture.
What the operators mean
{
layout: sequence;
|box| { fill: --purple-wash; stroke: --purple-deep; color: --purple-ink; }
}
|box#shop| "Storefront"
|box#pay| "Payments"
shop -> pay "charge $42"
pay -> pay "verify card"
pay --> shop "receipt"
shop ~> pay "queue settlement"
Three operators, three different things on the page:
->a call. It opens an activation bar on its target; the next return from that target closes it, and nested calls stack outward.a -> aa self-message. Internal work, hooked back onto the same lifeline. It opens no bar.~>async. Drawn wavy, and expecting no reply.
Repeating a span
{
layout: sequence;
|box| { fill: --rose-wash; stroke: --rose-deep; color: --rose-ink; }
|cyl| { fill: --teal-wash; stroke: --teal-deep; color: --teal-ink; }
|loop| { fill: --amber-wash; stroke: --amber-deep; }
}
|box#shop| "Storefront"
|box#pay| "Payments"
|cyl#db| "Orders"
shop -> pay "charge $42"
pay --> shop "receipt"
|loop| "each item" [
shop -> db "reserve stock"
db --> shop "in stock"
]
|note| "one round trip per line item" { place: over shop db; }
A |loop| frame wraps the rows that repeat, draws them once, and uses its
label as the guard.
Its [ ] groups messages for layout but opens no scope — the wires inside
still name the sequence’s own participants, which is why shop and db need
no path.
A |note| is a callout bound to lifelines by place::
over shop— on one lifeline.over shop db— spanning from one to another.left shop/right shop— beside one.
Branching
{
layout: sequence;
|box| { fill: --purple-wash; stroke: --purple-deep; color: --purple-ink; }
#pay { fill: --rose-wash; stroke: --rose-deep; color: --rose-ink; }
|alt| { fill: --purple-wash; stroke: --purple-deep; }
}
|box#user| "Customer"
|box#shop| "Storefront"
|box#pay| "Payments"
user -> shop "submit card"
shop -> pay "authorize"
|alt| "accepted" [
pay --> shop "approved"
shop --> user "receipt"
|else| "declined"
pay --> shop "refused"
shop --> user "ask for another card"
]
An |alt| holds two or more compartments split by |else|. Each label is that
branch’s guard, and the |alt|’s own label guards the first compartment.
|opt| is the same frame with a single branch, for a step that only sometimes
happens.
Go deeper
The full sequence reference covers activation control, frame nesting, note placement and the spacing knobs.