How to Add Optional Animation to a Diagram in cathrynlavery/diagram-design
In the cathrynlavery/diagram-design repository, you add optional animation to a diagram by declaring a data-motion-mode attribute on the root element, tagging items with data-motion-item and data-step, importing the canonical controller, and validating with the provided Python scripts.
The cathrynlavery/diagram-design skill treats optional animation as a presentation layer that never changes the underlying static meaning of a diagram. When you add optional animation to a diagram, the complete diagram must already exist in the DOM before any motion runs. The rules that govern this behavior are defined in skills/diagram-design/references/animation.md.
Choose an Animation Mode
The first step is declaring how the motion behaves. Add the data-motion-mode attribute to the root element of the diagram—typically the <svg> or a wrapper <div>.
The skills/diagram-design/references/animation.md reference file defines four valid values:
none— Renders a static diagram with no scripts. This is the default.reveal— Plays a single deterministic autoplay run that stops on completion.step— Enables a pause-able, step-wise animation with explicit playback controls.loop— Runs a decorative token that repeats indefinitely without changing meaning.
Load the Animation Controller On Demand
The repository loads motion assets only when a diagram requests them. The canonical controller lives in skills/diagram-design/assets/template-motion.html and serves as the HTML scaffold and script bundle for all animated diagrams.
If the root element carries a mode other than none, the skill loader pulls in animation.md and the controller template. Otherwise, the diagram remains script-free and static.
Tag Elements with Semantic Motion Primitives
Every animated element must be tagged with data-motion-item and assigned a numeric data-step="N" where N is between 1 and 8. The animation.md reference lists the allowed semantic primitives—such as Path draw, Staggered reveal, and Queue counter—along with their limits.
Only elements that carry the .motion-ready class are permitted to hide or transform during playback. This constraint keeps the animation predictable and scoped.
<div class="diagram" data-motion-mode="reveal" data-motion-root>
<svg viewBox="0 0 400 300">
<g data-motion-item data-step="1" class="motion-ready">
<!-- First element to appear -->
</g>
<g data-motion-item data-step="2" class="motion-ready">
<!-- Second element -->
</g>
</svg>
</div>
<script src="skills/diagram-design/assets/template-motion.html"></script>
Honor the Static-First Contract
Before any animation runs, the complete diagram—including all labels, connectors, and outcomes—must already be present in the HTML or SVG. The animation layer is strictly additive; it cannot introduce nodes that do not exist in the static markup.
CSS selectors scoped under .motion-ready are the only elements allowed to change visibility or geometry during playback. This static-first contract ensures that if scripts fail or motion is disabled, the diagram remains fully readable.
Provide Accessible Playback Controls
When you use data-motion-mode="step", you must supply native <button> controls for Play, Pause, Replay, Previous, and Next. Each button uses a data-motion-action attribute with values such as play, pause, replay, prev, or next.
These accessible controls must be keyboard-accessible and include proper ARIA labeling so users can navigate the step-wise animation without relying on a mouse.
<div class="diagram" data-motion-mode="step" data-motion-root>
<svg viewBox="0 0 400 300">
<!-- Static content plus ordered motion items -->
</svg>
<div data-motion-controls>
<button data-motion-action="play" aria-pressed="false">Play</button>
<button data-motion-action="pause" aria-pressed="false">Pause</button>
<button data-motion-action="prev">Previous</button>
<button data-motion-action="next">Next</button>
<button data-motion-action="replay">Replay</button>
</div>
</div>
<script src="skills/diagram-design/assets/template-motion.html"></script>
Validate with the Built-In Verification Scripts
After you add optional animation to a diagram, run the verification suite to confirm the contract is honored. The repository provides three scripts in the scripts/ directory:
python3 scripts/verify-motion.py path/to/diagram.html— Checks mode declarations, step continuity, timing budgets, and accessibility.python3 scripts/test-verify-motion.py— Exercises the verifier against adversarial modifications.python3 scripts/lint-skin.py path/to/diagram.html— Validates that the controller matches the canonical template and catches disallowed skin changes.
python3 scripts/verify-motion.py path/to/diagram.html
python3 scripts/test-verify-motion.py
python3 scripts/lint-skin.py path/to/diagram.html
Respect Reduced-Motion and Export Fallbacks
When a user prefers reduced motion, the CSS defined in skills/diagram-design/references/animation.md forces a static frame by collapsing animation durations and hiding all playback controls. The same static frame is used when printing or exporting to PNG and SVG.
To explicitly disable animation and keep a diagram static, set data-motion-mode="none" and omit the controller script:
<div class="diagram" data-motion-mode="none">
<svg viewBox="0 0 400 300">…</svg>
</div>
Summary
- Add optional animation to a diagram by choosing one of four motion modes in
data-motion-mode:none,reveal,step, orloop. - Tag animated elements with
data-motion-itemanddata-step="1"throughdata-step="8", and restrict visual changes to the.motion-readyclass. - Load the canonical
skills/diagram-design/assets/template-motion.htmlcontroller only when motion is required. - For
stepmode, include native buttons withdata-motion-actionattributes and ARIA labels. - Validate your work with
scripts/verify-motion.py,scripts/test-verify-motion.py, andscripts/lint-skin.py. - Honor reduced-motion preferences automatically through the CSS contract in
animation.md.
Frequently Asked Questions
What is the maximum number of animation steps allowed per diagram?
The skills/diagram-design/references/animation.md contract allows steps numbered 1 through 8. Each animated element must declare its order with a data-step attribute inside that range.
Can I write a custom animation controller instead of using the canonical template?
No. The skills/diagram-design/assets/template-motion.html file is the canonical controller, and scripts/lint-skin.py checks for disallowed deviations. Using a custom controller would break the repository’s static-first contract and fail verification.
How does the diagram behave if JavaScript is disabled or the controller fails to load?
Because the complete diagram is rendered in the static markup before any animation runs, a missing controller or disabled JavaScript leaves the user with a fully readable static diagram. The .motion-ready class is the only scope permitted to alter visibility, so the baseline content remains intact.
What happens when a user has prefers-reduced-motion enabled?
The CSS in skills/diagram-design/references/animation.md forces an immediate static frame by collapsing animation durations and hiding all motion controls. This same static frame is also used for print and raster exports, ensuring the diagram is accessible and deterministic across all environments.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →