SeqDia
Interactive sequence diagrams for React
Model actors as a tree with collapsible groups. Messages route to visible leaves—expand a group to reveal child actors, collapse to roll messages up to the parent.
Live example
Click actor headers to expand/collapse groups. Try the controls to see highlighting and selection in action.
Start checkoutbrowser → frontend
Authenticatefrontend → auth
Load profileauth → database
Profile readydatabase → auth
Auth completeauth → frontend
Create intentfrontend → payments
Validate cartpayments
Persist intentpayments → database
Intent storeddatabase → payments
Confirmpayments → frontend
Render receiptfrontend → browser
Quick start
Install and render a diagram in minutes.
Install
pnpm add seqdia
Requires react and react-dom as peer dependencies. Tailwind CSS is expected for styling.
import {
SequenceDiagram,
useSequenceController,
defineLeafDiagram,
} from "seqdia";
const model = defineLeafDiagram({
actors: [
{ actorId: "a", label: "Service A" },
{ actorId: "b", label: "Service B" },
],
messages: [
{ messageId: "m1", fromActorId: "a",
toActorId: "b", label: "Request" },
],
});
function Diagram() {
const controller = useSequenceController(model);
return (
<SequenceDiagram
model={model}
controller={controller}
/>
);
}Controller API
The controller manages diagram state. Create one with useSequenceController(model).
Expansion
expandActor(id)collapseActor(id)toggleActorExpansion(id)setExpandedActors(Set)
Highlighting
highlightActors(ids)highlightMessages(ids)clearHighlights()
Transient emphasis, typically on hover
Selection
selectActors(ids)selectMessages(ids)toggleActorSelection(id)toggleMessageSelection(id)clearSelection()
Persistent state, typically on click
const controller = useSequenceController(model);
// Expand/collapse groups
controller.expandActor("auth");
controller.collapseActor("payments");
controller.toggleActorExpansion("auth");
// Highlight actors or messages (visual emphasis)
controller.highlightActors(["auth", "payments"]);
controller.highlightMessages(["auth-session", "intent"]);
controller.clearHighlights();
// Select actors or messages (persistent state)
controller.selectMessages(["confirm"]);
controller.toggleActorSelection("database");
controller.clearSelection();
// Access current state
const { highlight, selection, expandedActors } = controller.state;Custom rendering
Use render props to fully customize actors and messages.
<SequenceDiagram
model={model}
controller={controller}
getActorStyle={(actor) => ({
color: palette[actor.actorId],
})}
getMessageStyle={(message) => ({
strokeColor: palette[message.fromActorId],
})}
renderActor={({ actor, buttonProps, highlighted }) => (
<button {...buttonProps} className={cn("btn", highlighted && "ring-2")}>
{actor.label}
</button>
)}
renderMessage={({ resolved, messageProps }) => (
<div {...messageProps}>
<MessageArrow direction={resolved.direction} stroke="#333" />
<span>{resolved.message.label}</span>
</div>
)}
onActorClick={(id) => console.log("Actor:", id)}
onMessageClick={(id) => console.log("Message:", id)}
/>