# Diagram-Design Animation Modes: A Complete Guide to None, Reveal, Step, and Loop

> Explore Diagram Design's four animation modes: none, reveal, step, and loop. Understand their accessibility contract, ensuring diagrams are available for all users before motion.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: deep-dive
- Published: 2026-09-13

---

**Diagram-Design implements four mutually exclusive animation modes—`none`, `reveal`, `step`, and `loop`—each governed by a strict static-first accessibility contract that guarantees full diagram availability for screen readers and reduced-motion users before any motion is applied.**

The cathrynlavery/diagram-design repository treats animation as **optional progressive enhancement**, not a required feature. This philosophy is codified in [`skills/diagram-design/references/animation.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/animation.md), where every mode adheres to a contract ensuring assistive technologies always encounter complete, navigable diagrams regardless of JavaScript or CSS availability.

## The Four Animation Modes Explained

Each mode is declared via `data-motion-mode="…"` on a container with `data-motion-root`. The modes are **exclusive**—a diagram cannot combine, for example, `reveal` and `step` behaviors.

### `none`: Static-First Default

The `none` mode produces a **fully stable figure with zero JavaScript dependency**.

- **Behavior**: The diagram renders exactly as authored, with no motion, no controls, and no timing considerations.
- **Implementation**: Pure HTML/SVG; no [`template-motion.html`](https://github.com/cathrynlavery/diagram-design/blob/main/template-motion.html) controller loads.
- **Use cases**: Print workflows, screenshot capture, email embeds, and environments where motion is explicitly unwanted.

```html
<div data-motion-root data-motion-mode="none">
  <!-- Complete SVG content visible immediately -->
  <svg aria-labelledby="diagram-title">
    <title id="diagram-title">System Architecture Overview</title>
    <!-- All nodes, edges, and labels fully rendered -->
  </svg>
</div>

```

According to the animation contract in [`animation.md`](https://github.com/cathrynlavery/diagram-design/blob/main/animation.md), `none` is the **implicit default** when no `data-motion-mode` is specified.

### `reveal`: Deterministic Autoplay

The `reveal` mode executes a **single deterministic animation sequence that stops at the final frame**.

- **Behavior**: Content appears progressively on load, then stabilizes permanently.
- **Implementation**: CSS-only for sequences ≤5 seconds; longer sequences trigger the **scoped controller** from [`skills/diagram-design/assets/template-motion.html`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/template-motion.html).
- **Use cases**: Ordered explanations like request flows, where one automated walkthrough suffices.

```html
<div data-motion-root data-motion-mode="reveal">
  <path data-motion-item data-step="1" class="motion-reveal" d="..."/>
  <path data-motion-item data-step="2" class="motion-reveal" d="..."/>
  <path data-motion-item data-step="3" class="motion-reveal" d="..."/>
</div>

```

The reveal timing follows fixed CSS variables: `--motion-fast: 160ms`, `--motion-step: 480ms`, `--motion-hold: 720ms`. Total sequence budget: **8 seconds maximum**.

### `step`: User-Controlled Progressive Disclosure

The `step` mode presents **paused semantic states** that users advance manually via explicit controls.

- **Behavior**: Diagram begins at step 0 (static preview or blank canvas); user controls pacing.
- **Implementation**: Inline JavaScript from [`template-motion.html`](https://github.com/cathrynlavery/diagram-design/blob/main/template-motion.html) binds **Play, Pause, Replay, Previous, and Next** buttons to the nearest `data-motion-root`.
- **Use cases**: Teaching scenarios, policy trace diagrams, comparative analysis—any context where audience control improves comprehension.

```html
<div data-motion-root data-motion-mode="step">
  <g data-motion-item data-step="1" aria-label="Initial request">
    <rect .../>
  </g>
  <g data-motion-item data-step="2" aria-label="Validation layer">
    <rect .../>
  </g>
  <g data-motion-item data-step="3" aria-label="Response construction">
    <rect .../>
  </g>
</div>

<!-- Control panel injected by controller -->
<div data-motion-controls>
  <button data-motion-action="prev">Previous</button>
  <button data-motion-action="play">Play</button>
  <button data-motion-action="pause">Pause</button>
  <button data-motion-action="next">Next</button>
  <button data-motion-action="replay">Replay</button>
</div>

```

The DOM order of `data-motion-item` elements **must match narrative order**; at most two items appear per step to prevent cognitive overload.

### `loop`: Decorative Repetition

The `loop` mode enables **endless decorative motion that adds no semantic meaning**.

- **Behavior**: Pure CSS animation repeats indefinitely (minimum 3-second cycle).
- **Implementation**: No JavaScript required; `data-motion-decorative` marks non-essential elements.
- **Use cases**: Subtle visual indicators like "live data" tokens or attention-directing pulses.

```html
<div data-motion-root data-motion-mode="loop">
  <!-- Diagnostic: this element loops but conveys no information -->
  <circle data-motion-decorative 
          class="motion-pulse" 
          cx="50" cy="50" r="5"/>
</div>

```

The `loop` mode is **strictly decorative** per the contract. No diagram may rely on loop animation to communicate essential relationships.

## The Accessibility Contract: Static-First Enhancement

The [`animation.md`](https://github.com/cathrynlavery/diagram-design/blob/main/animation.md) specification mandates **seven guarantees** that protect users regardless of their technology stack or motion preferences.

### 1. Source Completeness

All semantic content—nodes, labels, connectors, outcomes—must be **present in the raw HTML/SVG before motion enhancement**. Only elements within `.motion-ready` containers may be hidden or transformed.

### 2. Stable Capture Frame

Every animated diagram must expose a **`data-frame="static"`** (or `?motion=static` query) view that:
- Displays the **complete diagram**
- Hides all playback controls
- Serves print, screen-reader narration, and SVG/PNG export workflows

### 3. CSS-Driven Presentation

Visual changes use **CSS transitions and keyframes exclusively**. JavaScript scope is limited to:
- Control binding
- Step attribute updates
- Single deterministic timer management

**Prohibited**: network fetches, DOM injection, geometry measurement, `requestAnimationFrame` loops for layout.

### 4. Deterministic Timing

All timing derives from fixed CSS custom properties:
- `--motion-fast: 160ms`
- `--motion-step: 480ms`
- `--motion-hold: 720ms`

**Hard limit**: 8 seconds total motion budget. Randomness, spring physics, and `setInterval` polling are forbidden.

### 5. Explicit Step Ordering

Animated items declare narrative position:
- `data-motion-item` marks animatable elements
- `data-step="N"` where N ∈ [1, 8]
- Maximum **two items per step**

### 6. Scoped State

Controls affect **only the nearest `data-motion-root`**. IDs, timers, and ARIA live regions never cross figure boundaries, enabling multiple animated diagrams per page without collision.

### 7. Failure-Safe Startup

The `.motion-ready` class attaches **only after successful control binding**. Any script error leaves the complete static source visible—no broken half-animations.

## Reduced-Motion and Print Support

The contract enforces **automatic degradation** for users who need it.

The `prefers-reduced-motion: reduce` media query triggers:
- Forced **static frame display**
- Control hiding
- Decorative motion suppression (`[data-motion-decorative]`)

Print styles replicate this behavior, ensuring **physical and digital accessibility parity**.

```css
@media (prefers-reduced-motion: reduce), print {
  [data-motion-root] {
    --motion-enabled: 0;
  }
  
  [data-motion-controls] {
    display: none !important;
  }
  
  [data-motion-item] {
    opacity: 1 !important;
    transform: none !important;
  }
  
  [data-motion-decorative] {
    display: none;
  }
}

```

## Verification and Compliance

The repository includes automated enforcement of the animation contract:

| Tool | Path | Purpose |
|------|------|---------|
| [`verify-motion.py`](https://github.com/cathrynlavery/diagram-design/blob/main/verify-motion.py) | [`scripts/verify-motion.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-motion.py) | CI script validating mode declarations, step counts, timing limits, and ARIA compliance |
| [`self_check.py`](https://github.com/cathrynlavery/diagram-design/blob/main/self_check.py) | [`skills/diagram-design/scripts/self_check.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/self_check.py) | Runtime diagnostic agents invoke to verify generated diagrams |
| [`template-motion.html`](https://github.com/cathrynlavery/diagram-design/blob/main/template-motion.html) | [`skills/diagram-design/assets/template-motion.html`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/template-motion.html) | Canonical controller implementation for `reveal` and `step` modes |
| [`example-policy-trace-animated.html`](https://github.com/cathrynlavery/diagram-design/blob/main/example-policy-trace-animated.html) | [`skills/diagram-design/assets/example-policy-trace-animated.html`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/example-policy-trace-animated.html) | Reference implementation demonstrating full contract compliance |

Running `python scripts/verify-motion.py --strict` fails the build if any diagram violates timing budgets, misses required attributes, or lacks static frame exposure.

## Summary

- **Four exclusive modes**—`none`, `reveal`, `step`, `loop`—cover static, autoplay, interactive, and decorative motion needs.
- **Static-first architecture** guarantees complete diagram availability before any JavaScript or CSS enhancement.
- **Strict timing and scope limits** (8s budget, scoped controllers, CSS-only presentation) ensure predictable, performant behavior.
- **Automatic reduced-motion support** via `prefers-reduced-motion` and print styles provides accessible fallbacks without author intervention.
- **Automated verification** through [`verify-motion.py`](https://github.com/cathrynlavery/diagram-design/blob/main/verify-motion.py) enforces contract compliance in CI pipelines.

## Frequently Asked Questions

### What happens if JavaScript fails to load in a `step` or `reveal` diagram?

The diagram remains fully visible and functional. The `.motion-ready` class—required to hide or transform any content—is only added after successful controller initialization from [`template-motion.html`](https://github.com/cathrynlavery/diagram-design/blob/main/template-motion.html). A script error leaves all `data-motion-item` elements in their default visible state, satisfying the source completeness guarantee.

### Can I combine multiple animation modes in one diagram?

No. The `data-motion-mode` attribute accepts exactly one value: `none`, `reveal`, `step`, or `loop`. These modes are mutually exclusive by design. If you need both autoplay and manual control, create two diagram variants or use `step` mode with an auto-advance option (not part of the core contract).

### How does `prefers-reduced-motion` interact with the `loop` mode?

Decorative loops cease entirely. The media query forces `display: none` on `[data-motion-decorative]` elements and disables all CSS animations. The `loop` mode is intentionally non-semantic, so its suppression never removes information—only visual polish.

### What's the maximum number of steps allowed in `step` mode?

Eight steps maximum, with at most two `data-motion-item` elements appearing per step. This constraint—enforced by [`verify-motion.py`](https://github.com/cathrynlavery/diagram-design/blob/main/verify-motion.py)—prevents cognitive overload and maintains the 8-second total motion budget even at maximum step duration (`--motion-step: 480ms` × 8 = 3.84s active animation plus hold time).