Action types
The following action types are available. All share a set of common fields
(timeline lifecycle: id, duration,
wait_for, keep_until, keep_until_next, keep_until_end).
move
Moves a dynamic object from from to to.
{
type: 'move',
object: 'req', // id of a packet
from: 'browser', // id of a node
to: 'api', // id of a node
duration: 600,
}
Produces two breakpoints: appearance and arrival. By default, the object disappears at the end of its animation.
arrow
Draws an animated arrow between two nodes (progressive drawing).
{
type: 'arrow',
from: 'a',
to: 'b',
style: 'dashed', // 'solid' | 'dotted' | 'dashed' | 'animated'
path: 'bezier', // 'bezier' | 'simplebezier' | 'straight' | 'step' | 'smoothstep'
arrow_head: 'both', // 'forward' | 'backward' | 'both' | 'none'
text: 'request',
}
For permanent arrows (decor displayed right from the initialization),
use the connections root array instead.
parallel
Wraps child actions executed at the same time.
{
type: 'parallel',
actions: [
{ type: 'move', object: 'p1', from: 'a', to: 'b' },
{ type: 'arrow', from: 'c', to: 'd' },
],
}
The wait_for and keep_until inside a parallel continue to
work normally. Here a move and an arrow of different types start at the
same instant.
loading
Displays a loading spinner on a target node (simulates processing).
{ type: 'loading', object: 'db', duration: 900 }
set_content
Mutates the content of a node. The content follows the ObjectContent shape, shared
avec node.content (voir content)
:
code: dark terminal with Prism highlighting, no URL bar; the font adjusts to fit the longest line without wrapping.text: browser window with a configurable URL bar (url).image: image (value= path/URL) displayed in a window.table: data table (columns+rows_data).
valueThe content-bearing field is named value (not content). The content is
the wrapping object.
code mode:
{
type: 'set_content',
object: 'editor',
content: {
type: 'code',
language: 'javascript',
value: 'const add = (a, b) => a + b;',
},
}
text mode (browser window with address bar):
{
type: 'set_content',
object: 'browser',
content: {
type: 'text',
url: 'exemple.com/users',
value: 'Alice\nBob',
},
}
table mode:
{
type: 'set_content',
object: 'admin',
content: {
type: 'table',
columns: ['id', 'nom'],
rows_data: [
[1, 'Alice'],
[2, 'Bob'],
],
},
}
| Field | Affected modes | Role |
|---|---|---|
type | all | code | text | image | table. |
value | code/text/image | Source text, or image path. |
language | code | Highlighting language (cf. HighlightLanguage). |
url | text | Address bar of the window. |
columns | table | Column headers. |
rows_data | table | Data rows. |
The three modes, side by side (code, text, then table):
comment
Displays a text bubble fading in near a node, identified by object.
{
type: 'comment',
object: 'browser',
text: 'The user clicks',
duration: 400,
}
Omniscient comment: omit object to display the bubble at the top
of the scene rather than next to a node — ideal for a general narration that
is not attached to any specific component.
{ type: 'comment', text: 'Step 2 — Authentication' }
Below, an omniscient comment (top of the scene) followed by two bubbles attached to nodes:
set_visible
Shows or hides a static node with a fade. If this parameter is false (or
if the node has no initial visible in its configuration see
Nodes), it appears hidden.
The visibility state persists until the end of the timeline (or until
a contrary set_visible).
{ type: 'set_visible', object: 'cache', visible: true }
set_color
Recolors a static node at runtime. Mutates any of the three color channels —
background_color, border_color, text_color — over duration ms, with a
deterministic eased cross-fade between the previous color and the new one (via
CSS color-mix, so it stays scrubbable in both directions). Only the channels
you provide change; the others keep their current value.
{ type: 'set_color', object: 'node', background_color: '#1f2937', duration: 600 }
Same value space as the node colors: a predefined
CSS name (tomato, steelblue…) or an exact hex (#1a1a1a). The same
auto-derivations apply — a background_color without border_color derives a
coordinated border, and without text_color a high-contrast ink (outside
syntax-highlighted areas). The reached color persists until the end of the
timeline (like set_visible), and successive set_color on the same node
chain: each one cross-fades from the previous color.
This is the core operation for algorithm visualizations that recolor nodes — for instance the red/black recoloring of a red-black tree. Below, a node inserted "red" is recolored to "black":
set_color also recolors a permanent connection:
pass the connection's id as object and a single color (the three node
channels don't apply to a line). It cross-fades the line and its arrow head from
the current color — ideal for lighting up the edge a graph traversal just
followed:
{ type: 'set_color', object: 'edge', color: 'seagreen', duration: 500 }
set_icon
Updates a node's corner icon badge at runtime — the small overlaid badge
(icon: a known technology, a registered icon, or short free text). The badge
swaps to the new value when the action starts; the reached value persists
until the end of the timeline (like set_color), and successive set_icon on
the same node chain. An empty string clears the badge.
{ type: 'set_icon', object: 'v', icon: '7' }
This is how an algorithm visualization keeps a per-node scalar that evolves
legible on the node itself — a Dijkstra node's tentative distance (∞ → 7 → 5),
an A* node's f = g + h — rather than only in a comment. Below, a node's badge
walks from ∞ down to its final value:
rotate
Animates the visual rotation of a node. Two mutually exclusive modes; only the visual rotates (the label below stays upright), and the angle reached when the rotation ends persists until the end of the timeline.
Target angle to (degrees, clockwise): a single eased rotation. The
starting angle is the node's current rotation — its static
rotation field, or the
target of a previous rotate — so successive rotations chain.
{ type: 'rotate', object: 'gear', to: 90, duration: 600 }
A full turn is just to: 360 (from 0); rotate back with to: 0.
Continuous spin spin (degrees per second, signed — positive turns
clockwise, negative counter-clockwise): the node turns at a constant speed
(linear, no easing). How long it spins reuses the usual
timing fields — duration, keep_until, or
keep_until_end — instead of a target angle.
{ type: 'rotate', object: 'gear', spin: 360, keep_until_end: true } // until the end
{ type: 'rotate', object: 'gear', spin: -180, duration: 3000 } // 3 s, counter-clockwise
{ type: 'rotate', object: 'gear', spin: 90, keep_until: 'response' } // until action "response"
If both to and spin are given, spin wins.
rotate_subtree
Restructures a binary tree with a tree rotation around a pivot, then animates
the nodes gliding to their new places while the parent/child edges re-route.
Only valid in direction: 'tree', which
supplies the tree block this action mutates.
{ type: 'rotate_subtree', object: '10', rotation: 'left' } // or 'right'
A left rotation lifts the pivot's right child; a right rotation lifts its left child (the required child must exist, else a warning is emitted and nothing moves). A rotation preserves the tree's in-order traversal, so horizontal positions stay put — the motion is the pivot and the moved subtree changing depth.
Successive rotate_subtree actions chain (each starts from the topology the
previous one left), which is how AVL double rotations are expressed — an
LR case is a left rotation on the child followed by a right rotation on the
grandparent. Below, a single left rotation rebalances a right-leaning chain:
highlight
Highlights (pulsing halo) a static node or a permanent connection,
identified by their id.
{ type: 'highlight', object: 'db' }
Here the halo pulses first on the db node, then on the permanent
connection link:
To emphasize a connection from the start (no timeline action), use its static
highlighted field
instead.
flow
Animates an electric current circulating along a chain of wires — the
signature animation of an electrical schematic.
A train of evenly-spaced charge dots rides the route (an ordered list of
node / node:pin references forming a path or a closed loop), advancing one
full lap per duration ms and, by default, looping continuously. Each
consecutive pair of the route must be joined by an actual wire (connection), so
the charges follow the drawn path exactly.
{
type: 'flow',
route: ['battery:+', 'R1:a', 'R1:b', 'led:a', 'led:b', 'battery:-'],
color: '#f59e0b', // default: the theme accent
keep_until_end: true,
}
reverse: true sends the charges the other way (electron flow − → + instead of
conventional current + → −); loop: false plays a single pass; count sets how
many dots ride the route (default: about one per segment). Being a pure function
of t, the current scrubs both ways like everything else. See the Electrical
circuit demo in the gallery.
toggle
Flips an electrical switch / push_button between open and closed, swinging
the lever over duration ms. Like set_visible, the reached
state persists until the end of the timeline (or the next contrary toggle)
and scrubs both ways. Pair it with a flow that starts once the contact is
closed to show the circuit energizing.
{ type: 'toggle', object: 'sw', closed: true }
wait
Inserts a dead time: nothing happens for duration ms (default:
1000). The action produces no element on screen; it simply
delays the next step. Content already placed (via keep_until_next)
remains displayed during the wait, which freezes the frame for the desired time.
{ type: 'wait', duration: 1500 }
Useful to let the viewer read a step before continuing, or
to pace a playback in autoPlay.
Complete reference
For the exhaustive list of fields (types, default values, constraints), see the API reference generated from the JSON Schema.