How the Motion Controller Works in diagram-design and Why It Uses a Pinned Implementation

The diagram-design motion controller is a single, static-by-default JavaScript implementation housed in template-motion.html that enforces strict markup constraints through verify-motion.py to guarantee consistent animation behavior, accessibility, and security across all diagrams.

The cathrynlavery/diagram-design repository provides a specialized skill for creating animated technical diagrams with controlled motion. At its foundation lies a motion controller that is intentionally pinned to a specific implementation, preventing fragmentation of animation logic and ensuring every diagram meets strict standards for performance and accessibility.

Architecture of the Pinned Motion Controller

The motion system relies on a centralized controller file rather than distributed scripts. This architecture mandates that all motion-related logic emanates from a single source.

The Controller Implementation in template-motion.html

The sole JavaScript controller resides in [skills/diagram-design/assets/template-motion.html](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/template-motion.html). This file contains the complete logic for parsing motion attributes, managing animation timing, and generating playback controls. When a diagram includes motion markup, the DiagramParser builds a tree structure of roots, items, scripts, and controls, but defers all manipulation to the pinned controller.

The controller exposes standardized CSS custom properties such as --motion-fast and --motion-step to ensure consistent timing across all diagram instances. It also injects the interactive control layer—play, pause, replay, and step navigation—dynamically into the DOM.

Validation Through verify-motion.py

Before any diagram deploys, the [scripts/verify-motion.py](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-motion.py) linter validates the markup against a strict contract. The script enforces:

  • Exactly one root element: The markup must contain precisely one data-motion-root attribute, establishing the pinned controller anchor.
  • Hierarchy constraints: All data-motion-item elements must be children of the root.
  • Numerical rigor: Steps must be numbered with integer data-step values.
  • Budget limits: No more than 12 motion items and 8 steps per diagram.
  • Script isolation: Any additional or modified controller scripts cause the linter to fail, preserving the single-implementation constraint.

Why the Motion Controller Is Pinned to a Specific Implementation

Pinning the controller to the template-motion.html implementation is an intentional architectural decision documented in ADR 0001. This design delivers three critical guarantees.

Predictable Behavior and Timing Variables

By restricting motion logic to one controller, the system ensures that --motion-fast, --motion-step, and interaction models (reveal, play, pause) behave identically across every diagram. Developers cannot introduce conflicting timing functions or asynchronous scripts that desynchronize animations.

Accessibility Guarantees

The pinned controller emits a dedicated status region with role="status" and aria-live="polite" to screen readers, announcing step changes without requiring additional markup from authors. It also detects prefers-reduced-motion and automatically degrades to a complete static fallback, ensuring the diagram remains comprehensible when animation is disabled or when generating PNG exports.

Security and Consistency

The skin linter actively rejects any extra scripts or attempts to override the controller. This prevents injection of unsafe JavaScript and eliminates "controller drift" where different diagrams might implement incompatible animation patterns. The single-source truth in template-motion.html acts as a security boundary and a consistency enforcement mechanism.

Implementation Details and Code Examples

To enable motion, authors add specific data attributes to their HTML. The controller attaches automatically during the parsing phase.

Enabling Motion for a Diagram

<div data-motion-root data-motion-mode="reveal">
  <div data-motion-item data-step="1">First step</div>
  <div data-motion-item data-step="2">Second step</div>
  <!-- controls are auto-generated by the pinned controller -->
</div>

<script src="template-motion.html"></script>

Static Fallback for Export

When prefers-reduced-motion is active or for static file generation, the markup degrades gracefully:

<div data-motion-root data-frame="static" data-motion-mode="none">
  …complete diagram markup…
</div>

This fallback ensures that export pipelines and accessibility tools receive a fully rendered diagram without requiring JavaScript execution.

Summary

  • The motion controller lives exclusively in skills/diagram-design/assets/template-motion.html and is the only permitted source of animation logic.
  • verify-motion.py enforces a strict contract: one root, ≤12 items, ≤8 steps, and no extraneous scripts.
  • Pinning the implementation ensures predictable timing, accessibility compliance (including reduced-motion support), and security against script injection.
  • The system provides a static-by-default architecture where motion is opt-in (?motion=run) and always offers a complete fallback for non-JavaScript contexts.

Frequently Asked Questions

What file contains the motion controller logic?

All motion controller logic resides in [skills/diagram-design/assets/template-motion.html](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/template-motion.html). This single file handles parsing, timing, and interaction controls.

Why can't I use a custom JavaScript animation library?

The architecture explicitly forbids external controllers to guarantee consistent behavior and security. According to ADR 0001, allowing multiple implementations would fragment accessibility guarantees and violate the static-by-default principle. The verify-motion.py linter will fail any build that includes unauthorized scripts.

How does the system handle users who prefer reduced motion?

The pinned controller monitors prefers-reduced-motion and immediately degrades to a static representation. It also ensures a complete markup fallback is always available during initial render, satisfying both accessibility requirements and static export pipelines without requiring user-side JavaScript.

What are the limits on animation steps and items?

The validation script enforces a hard limit of 12 motion items and 8 steps per diagram. These constraints prevent performance degradation on low-power devices and ensure that complex animations remain cognitively manageable for users navigating via keyboard or assistive technology.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →