Sequence Diagram
define Complex System as sys define User as usr define Sequence Diagram as diagram define Other Users as usr2 begin sys, usr, usr2 sys ~> usr note over usr: "Take time to\nunderstand System" usr -> *diagram: Create usr -> usr2: Inform usr2 <-> diagram: Learn & understand usr2 -> sys: Use terminators box
Introduction
Want to draw a Sequence Diagram? Go to the online editor.
This library renders sequence diagrams from code. It is open-source (LGPL-3.0), and including it in a website is as simple as adding the script:
<script src="lib/sequence-diagram-web.js"></script>
If you are using NPM to manage dependencies, you can install with:
npm install --save svg-sequence-diagram
And import with:
import 'svg-sequence-diagram';
Or:
require('svg-sequence-diagram');
Any element with the class sequence-diagram
will automatically be
converted when the page loads:
A -> B: foo B -> A: bar
<pre class="sequence-diagram"> A -> B: foo B -> A: bar </pre>
Language
Connection Types
title Connection Types begin Foo, Bar, Baz Foo -> Bar: Simple arrow Bar --> Baz: Dashed arrow Foo <- Bar: Reversed arrow Bar <-- Baz: Reversed & dashed Foo <-> Bar: Double arrow Bar <--> Baz: Double dashed arrow # An arrow with no label: Foo -> Bar Bar ->> Baz: Different arrow Foo <<--> Bar: Mix of arrows Bar -> Bar: Bar talks to itself Foo -> +Bar: Foo asks Bar -Bar --> Foo: and Bar replies Bar -x Baz: Lost message # Arrows leaving on the left and right of the diagram [ -> Foo: From the left [ <- Foo: To the left Foo -> ]: To the right Foo <- ]: From the right [ ~> ]: Wavy left to right! # (etc.)
Dividers
title Dividers begin Foo, Bar, Baz Foo -> +Bar divider Bar -> +Baz divider delay: This takes a while -Baz --> Bar divider tear with height 20: Lots of stuff happens -Bar --> Foo
Notes & State
title Note Placements begin Foo, Bar note over Foo: Foo says something note left of Foo: Stuff note right of Bar: More stuff note over Foo, Bar: "Foo and Bar on multiple lines" note between Foo, Bar: Link # in long diagrams, we can add reminders of which agent is which: relabel text right: "Comments\nOver here!" state over Foo: Foo is ponderous
Logic
title At the Bank begin Person, ATM, Bank Person -> ATM: Request money ATM -> Bank: Check funds if fraud detected Bank -> Police: "Get 'em!" Police -> Person: "You're nicked" end Police else if sufficient funds ATM -> Bank: Withdraw funds repeat until "all requested money has been handed over" ATM -> Person: Dispense note end else ATM -> Person: Error end
Label Templates
autolabel "[<inc>] <label>" begin "Underpants\nGnomes" as A A <- ]: Collect underpants A <-> ]: ??? A <- ]: Profit!
Multiline Text
title "My Multiline Title" begin Foo, Bar note over Foo: "Also possible\nwith escapes" Foo -> Bar: "Lines of text\non this arrow" if "Even multiline\ninside conditions like this" Foo -> "Multiline\nagent" end state over Foo: "Newlines here, too!"
Themes
theme sketch title Mockup A thing -> +Another thing: Something happens -Another thing --> A thing: With some response note right of Another thing: Find out what happens here end Another thing
Available themes
- basic
- monospace
- chunky
- sketch
- sketch left handed
Short-Lived Agents
title "Baz doesn't live long" note over Foo, Bar: Using begin / end begin Baz Bar -> Baz Baz -> Foo end Baz note over Foo, Bar: Using * / ! # * and ! cause agents to be # created and destroyed inline Bar -> *Baz: make Baz Foo <- !Baz: end Baz # Foo and Bar end with black bars terminators bar # (options are: box, bar, cross, fade, none)
Agent Aliases
define My complicated agent name as A define "Another agent name, and this one's multi-line!" as B A -> B: this is much easier A <- B: than writing the whole name
Markdown
define "Name with **bold** and _italic_" as A define "Also `code` and ~strikeout~" as B A -> B: "_**basic markdown is supported!**_"
Alternative Agent Ordering
define Baz, Foo Foo -> Bar Bar -> Baz
Agent Types
begin User, Application, PostgreSQL User -> +Application Application -> +PostgreSQL -PostgreSQL --> Application -Application --> User User is a person PostgreSQL is a database
Asynchronous Communication
begin Initiator as I, Receiver as R # the '...id' syntax allows connections # to span multiple lines I -> ...fin1 ...fin1 -> R: FIN # they can even inter-mix! R -> ...ack1 R -> ...fin2 ...ack1 -> I: ACK ...fin2 -> I: FIN !I -> ...ack2 ...ack2 -> !R: ACK
More
More features are supported. See the online editor’s library and autocomplete features to discover them.
Browser Support
This has been tested in the latest versions of Google Chrome, Mozilla Firefox, and Apple Safari. Versions of Microsoft Internet Explorer / Edge have not been tested and probably won’t work. Any bugs found in a supported browser should be reported in the Issue Tracker.
API
For more advanced usage, an API is available:
import { SequenceDiagram } from 'svg-sequence-diagram'; // or const { SequenceDiagram } = require('svg-sequence-diagram'); var diagram = new SequenceDiagram(); diagram.set('A -> B\nB -> A'); document.body.appendChild(diagram.dom()); // Highlight elements created in line 1 (0-based) diagram.setHighlight(1);
Constructor
diagram = new SequenceDiagram(code, options); diagram = new SequenceDiagram(code); diagram = new SequenceDiagram(options); diagram = new SequenceDiagram();
Creates a new SequenceDiagram object. Options is an object which can contain:
code
: Alternative way of specifying code, instead of using a separate argument.container
: DOM node to append the diagram to (defaults to null).document
: Document object to base the diagram in (defaults to container's document, orwindow.document
).textSizerFactory
: Function which returns an object capable of measuring text (defaults to wrappinggetComputedTextLength
).themes
: List of themes to make available to the diagram (defaults to globally registered themes).namespace
: Each diagram on a page must have a unique namespace. By default a unique namespace is generated, but if you want something specific, enter it here.interactive
: Iftrue
, will automatically calladdInteractivity
when constructing the diagram.
.clone
newDiagram = diagram.clone(options); newDiagram = diagram.clone();
Creates a copy of the diagram. If options are given, they will override the
current diagram’s state (options is passed to the constructor of the new
object, so all the same options are available). Note that by default, the
namespace
will not be cloned (a new unique namespace will be
generated). Also the container
will not be cloned; you will need
to specify one explicitly or manually attach the new diagram at a later point.
.set
diagram.set(code);
Changes the code for the diagram and causes a re-render.
.process
processed = diagram.process(code);
Processes the given code but does not render it. Causes no change to the
diagram object. This is mostly useful for debounced rendering with immediate
error notifications. The resulting object can be passed to
render
at a later point.
.render
diagram.render(); diagram.render(processed);
Forces a re-render of the diagram. Typically this happens automatically.
Optionally, the result of an earlier call to
process
can be provided.
.addTheme
diagram.addTheme(theme);
Make a new theme available to the diagram. Any unrecognised themes are replaced with the default theme.
The theme API has not been finalised yet, so this method is not typically useful.
.getThemeNames
names = diagram.getThemeNames();
Returns a list of names of themes which are available to this diagram. These
can be specified in a theme <name>
line in the code.
.getThemes
themes = diagram.getThemes();
Returns a list of themes which are available to this diagram.
.addInteractivity
begin A, B if bored A -> +B -B --> A end if still bored A -> +B -B --> A end
diagram.addInteractivity();
Makes the rendered diagram interactive. Currently this means adding a click listener to any groups which causes them to collapse / expand. Try clicking on the example to the right.
The example here has CSS styling applied:
.region.collapsed, .region.expanded { cursor: pointer; user-select: none; } .region.collapsed:hover .outline, .region.expanded:hover .outline { fill: rgba(255, 128, 0, 0.5); }
It is also possible to enable interactivity using a HTML attribute:
<pre class="sequence-diagram" data-sd-interactive> A -> +B if something -B --> A end </pre>
.getSVGSynchronous
svgURL = diagram.getSVGSynchronous(options);
Returns a blob URL which contains the SVG code for the current diagram.
The options can include:
size
: Object containing optional width, height or zoom to specify in the SVG.
.getSVG
diagram.getSVG(options).then(({url, latest}) => { ... });
Asynchronous version of
getSVGSynchronous
. This is
provided for compatibility with getPNG
,
which has no synchronous equivalent.
The options can include:
size
: Object containing optional width, height or zoom to specify in the SVG.
The callback receives an object containing:
url
: The URL of the generated blob.latest
: True if the URL given is still valid; subsequent calls to this method will invalidate previous URLs.
.getPNG
diagram.getPNG(options).then(({url, latest}) => { ... });
Generates a PNG image and returns a blob URL.
The options can include:
resolution
: Desired pixels-per-unit.size
: Object containing optional width, height or zoom to render the image at (defaults to the unit size of the diagram). The final output will have sizewidth * resolution
×height * resolution
.
The callback receives an object containing:
url
: The URL of the generated blob.latest
: True if the URL given is still valid; subsequent calls to this method will invalidate previous URLs.
.getSize
size = diagram.getSize();
Returns an object containing width
and height
properties, corresponding to the size of the diagram in units.
.getTitle
title = diagram.getTitle();
Returns the document title as a string. All formatting is lost, and newlines are replaced with spaces. Returns a blank string if no title is set.
.setContainer
diagram.setContainer(node);
Same as calling node.appendChild(diagram.dom())
.
.dom
node = diagram.dom();
Returns the base SVG element which the diagram has been rendered into.
.setHighlight
diagram.setHighlight(line); diagram.setHighlight();
Marks elements generated by the specified line with a "focus" CSS class, which
can be used to style them. Only one line can be highlighted at a time. Calling
with no parameter (or null
) will remove the highlighting.
The outline effect seen in the editor can be achieved by targetting
.focus .outline
. All elements contain an element with the class
"outline", which defines a simple shape surrounding the entire element. For
example:
.region.focus .outline { stroke-width: 5px; stroke: rgba(255, 128, 0, 0.5); }
.setCollapsed
diagram.setCollapsed(line, collapsed, options); diagram.setCollapsed(line, collapsed);
Marks the given line as collapsed or non-collapsed. If an element defined at that line can be collapsed, it will be modified during the next render. Returns true if a change occurred, or false if the line already had the requested state.
line
can also be an array of lines.
By default, calling this method will trigger an automatic render (unless called
as a no-op). This can be disabled by passing {render: false}
in the
options argument.
.isCollapsed
collapsed = diagram.isCollapsed(line);
Returns true if the given line is marked as collapsed, regardless of whether that line being collapsed has a meaningful impact on the rendered document.
.collapse
diagram.collapse(line, options); diagram.collapse(line);
Shorthand for .setCollapsed(line, true, options)
.
.expand
diagram.expand(line, options); diagram.expand(line);
Shorthand for .setCollapsed(line, false, options)
.
.toggleCollapsed
diagram.toggleCollapsed(line, options); diagram.toggleCollapsed(line);
Toggles the given line’s collapsed status by calling
.setCollapsed
.
.expandAll
diagram.expandAll(options); diagram.expandAll();
Marks all lines as non-collapsed. Returns true if a change occurred, or false if all lines were already non-collapsed.
By default, calling this method will trigger an automatic render (unless called
as a no-op). This can be disabled by passing {render: false}
in the
options argument.
.addEventListener
diagram.addEventListener(type, callback);
Registers an event listener. The available events are:
mouseover
: called when the mouse enters a region of the diagram (e.g. a note).mouseout
: called when the mouse leaves a region of the diagram.click
: called when the user clicks on a region of the diagram.dblclick
: called when the user double-clicks on a region of the diagram.render
: called when the diagram finishes rendering. Receives the sequence diagram object as an argument.
All mouse events are invoked with a single parameter: the element. This object contains:
ln
: the line number of the source code which defined the element.type
: a string representing the type of the element.- Other fields which define the element (exact fields vary by type).
.removeEventListener
diagram.removeEventListener(type, callback);
Removes a previously registered event listener.
.removeAllEventListeners
diagram.removeAllEventListeners(type); diagram.removeAllEventListeners();
Removes all registered event listeners for a given type, or all event listeners for all types.
Similar Tools
There are quite a lot of sequence diagram drawing tools available. If this one doesn’t fit your needs for whatever reason, you might want to take a look at the alternatives: (but also feel free to raise feature requests in the issue tracker!)
- websequencediagrams.com is a commercial offering which inspired the syntax of this project and many others. It has a wide range of themes but limited functionality. Also offers a hosted image generation service.
- js-sequence-diagrams is a Javascript library which has wider browser support via snap.svg but very limited functionality.
- mermaid is a Javascript library and online editor which can render multiple types of UML diagram, including simple sequence diagrams.
- Scruffy UML is a Python library which can render multiple types of UML diagram, including simple sequence diagrams, from the commandline. Uses yUML syntax rather than the human friendly syntax used by most other projects.
- PlantUML is a Java project and online editor which can render multiple types of UML diagram, including sequence diagrams. Has a good range of features and allows a high degree of customisation (e.g. diagram colours).
Thanks
Thanks to the other tools mentioned above for inspiring parts of the syntax of this project, and to the Handlee font which is used in the sketch theme.
theme sketch begin User, SequenceDiagram as SD, Parser, Generator, Renderer User -> +SD: code SD -> +Parser: code -Parser --> SD: parsed SD -> +Generator: parsed -Generator --> SD: generated -SD -> +Renderer: generated -Renderer -> *DOM: SVG User <~> DOM: interaction terminators box