How to Configure Optional Motion Animations with the Accessibility Contract in Diagram Design

Diagram Design enforces a strict accessibility contract that requires all motion to start from a complete static diagram, preserve semantic content for assistive technology, and provide a reduced-motion fallback via prefers-reduced-motion: reduce.

To configure optional motion animations with the accessibility contract in diagram design, developers implement a static-first enhancement pattern that validates against the motion verifier scripts in the cathrynlavery/diagram-design repository. This approach guarantees that every animated diagram remains fully accessible while supporting progressive disclosure, teaching sequences, and decorative flow hints.

Understanding the Accessibility Contract

The accessibility contract is a binding specification that governs how motion may be added to diagrams. It is enforced by the motion verifier (scripts/verify‑motion.py and scripts/verify‑semantic‑motion.py), which checks for compliance before deployment.

Static-First Requirement

Every animation must start from a complete static diagram. All semantic content—including labels, connectors, and statuses—must be present in the source HTML/SVG before any motion is applied. This ensures that if JavaScript fails or motion is disabled, the diagram remains fully readable.

Semantic Preservation

Decorative elements must be hidden from assistive technology using aria‑hidden="true" and focusable="false", while semantic text appears exactly once in the accessibility tree. The SVG <title> and <desc> elements must describe the full meaning of the diagram without requiring animation to understand the content.

Reduced-Motion Guarantee

The contract mandates that prefers‑reduced‑motion: reduce forces the diagram into its final static frame, hides playback controls, and disables decorative motion. This media query also triggers for print media (@media print) and static exports (?motion=static).

Motion Modes and Constraints

Diagram Design supports four distinct motion modes defined by the data‑motion‑mode attribute. Only the reveal mode may autoplay, and it must run once on load when motion is explicitly requested.

Mode Behavior Implementation Typical Use
none Fully static, no JavaScript No controller, plain HTML Default, print, screenshots
reveal One deterministic autoplay run ending in final state CSS-only (≤ 5 s) or scoped controller Short ordered explanations
step Paused semantic states with interactive controls Minimal inline JS for Play/Pause Teaching, policy traces
loop Decorative token repeats without changing meaning CSS-only default Quiet flow hints (≥ 3 s cycle)

The reveal mode never restarts on viewport re-entry and can be replayed only via the explicit Replay control. The loop mode is restricted to purely decorative tokens that do not convey semantic information.

Required Markup Structure

To configure optional motion animations with the accessibility contract in diagram design, apply the following data attributes exactly as specified in [skills/diagram-design/references/animation.md](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/animation.md):

  1. Single root container: One element with data‑motion‑root and a valid data‑motion‑mode (none|reveal|step|loop).
  2. Motion items: Each animated element requires data‑motion‑item and an integer data‑step attribute defining its sequence.
  3. Decorative markers: Purely visual items must include data‑motion‑decorative.
  4. Live region: A container with role="status" and aria‑live="polite" must exist outside the controls to announce step changes (e.g., “Step 3 of 5: first divergence”).

Accessibility Implementation

Semantic motion requires specific ARIA markup and keyboard interaction patterns defined in the contract.

Decorative Overlays

Decorative elements carry aria‑hidden="true" and focusable="false" (see lines 95‑99 of the reference documentation). The verifier automatically checks for these attributes on items marked with data‑motion‑decorative.

Keyboard Controls

Interactive diagrams must use native <button> elements with data‑motion‑action attributes (play, pause, prev, next, replay). These buttons must expose focus, aria‑pressed, and disabled states. Arrow keys, Home/End, Space, and R (replay) operate on the motion root without stealing focus.

Live Status Region

The status container announces meaningful step changes but not every frame. Place this element outside the control block to prevent interference with assistive technology navigation.

Reduced-Motion and Print Fallbacks

The contract requires CSS that responds to user preferences and output media:

  • Reduced motion: @media (prefers-reduced-motion: reduce) forces all items to opacity: 1 and transform: none, hides decorative elements with display: none, and removes playback controls.
  • Print: @media print applies the same static presentation as reduced motion.
  • Export: Static exports use the query parameter ?motion=static to trigger the final frame view.

Verification Workflow

Before deploying an animated diagram, run the verification scripts to confirm compliance with the accessibility contract.

Basic motion verification:

python3 scripts/verify-motion.py path/to/diagram.html

Semantic and accessibility verification:

python3 scripts/verify-semantic-motion.py path/to/diagram.html

These scripts validate:

  • Single data‑motion‑root element and valid data‑motion‑mode.
  • Correctly scoped data‑motion‑item elements with integer data‑step attributes.
  • Proper ARIA markup for decorative items.
  • Presence of live status region.
  • Reduced-motion CSS that makes every item fully visible.

Code Examples

The canonical controller implementation lives in assets/template‑motion.html and must be used verbatim for any animated diagram.

Step Animation Implementation

This example demonstrates a minimal step mode animation with semantic items and accessible controls:

<div data-motion-root data-motion-mode="step" data-frame="static">
  <!-- Semantic items -->
  <g data-motion-item data-step="1" class="is-visible">
    <text>Step 1 Label</text>
  </g>
  <g data-motion-item data-step="2">
    <text>Step 2 Label</text>
  </g>

  <!-- Controls (copied from template-motion.html) -->
  <div data-motion-controls>
    <button data-motion-action="play"   aria-pressed="false">▶︎</button>
    <button data-motion-action="pause"  disabled>‖</button>
    <button data-motion-action="prev"   disabled>←</button>
    <button data-motion-action="next"   disabled>→</button>
    <button data-motion-action="replay" disabled>↺</button>
  </div>

  <!-- Live status region -->
  <div role="status" aria-live="polite" aria-atomic="true"></div>
</div>

All attributes are defined exactly as required by the contract; the diagram starts static, then steps through the two items when the user clicks Play.

Reveal Animation with CSS Timing

For deterministic autoplay that ends in a static state, use reveal mode with CSS-only timing:

<div data-motion-root data-motion-mode="reveal">
  <g data-motion-item data-step="1" class="is-visible">
    <text>First item</text>
  </g>
  <g data-motion-item data-step="2">
    <text>Second item</text>
  </g>
  <style>
    .motion-ready [data-motion-item] {
      transition: opacity var(--motion-step) var(--motion-ease),
                  transform var(--motion-step) var(--motion-ease);
    }
    .motion-ready [data-motion-item].is-visible { 
      opacity: 1; 
      transform: none; 
    }
  </style>
</div>

Because the mode is reveal, the CSS automatically animates the two items once on load and then remains at the final static frame.

Decorative Tokens

Mark purely visual animations with data‑motion‑decorative to ensure they are hidden from assistive technology when reduced motion is preferred:

<g data-motion-decorative data-motion-item data-step="1">
  <path d="M10 10 L90 90" stroke="orange" pathLength="1"
        stroke-dasharray="1" stroke-dashoffset="1"></path>
</g>

The token is hidden from assistive tech (aria‑hidden added by the verifier) and will be removed when the user’s system prefers reduced motion.

Key Files in the Repository

Summary

  • Configure optional motion animations with the accessibility contract in diagram design by applying the static-first enhancement pattern and validating with verify-motion.py.
  • Always include a single data-motion-root with a valid mode (none, reveal, step, or loop) and sequential data-step attributes on items.
  • Preserve accessibility by hiding decorative elements with aria-hidden, maintaining semantic text in the SVG title/desc, and implementing a live status region.
  • Enforce reduced-motion compliance through @media (prefers-reduced-motion: reduce) that forces final-frame visibility and hides controls.
  • Use the canonical controller from template-motion.html verbatim to ensure consistent keyboard navigation and ARIA behavior.

Frequently Asked Questions

What is the accessibility contract in Diagram Design?

The accessibility contract is a binding specification that guarantees all motion starts from a complete static diagram, preserves semantic content for assistive technology, and provides a reduced-motion fallback. It is enforced by the motion verifier scripts (verify-motion.py and verify-semantic-motion.py) which validate markup structure, ARIA attributes, and CSS fallbacks before deployment.

How do I verify that my diagram meets the motion accessibility requirements?

Run python3 scripts/verify-motion.py path/to/diagram.html to check for structural compliance (single root, valid modes, step ordering). For comprehensive accessibility validation including ARIA markup and reduced-motion CSS, run python3 scripts/verify-semantic-motion.py. Both scripts exit with error codes if the accessibility contract is violated.

Which motion mode should I use for teaching materials?

Use step mode for teaching and policy traces. This mode presents paused semantic states with interactive Play/Pause/Previous/Next controls, allowing learners to navigate through complex diagrams at their own pace while maintaining full keyboard accessibility and screen reader compatibility via the live status region.

How does the reduced-motion fallback work?

When a user has prefers-reduced-motion: reduce enabled, the diagram immediately renders in its final static state with all items fully visible (opacity: 1, transform: none), decorative elements hidden (display: none), and playback controls removed. The same presentation applies to print media and static exports (?motion=static), ensuring no information is lost when motion cannot be perceived.

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 →