Skip to content

Feature: motion tokens (duration, easing) with prefers-reduced-motion fallback #47

@oknemixam

Description

@oknemixam

Summary

DESIGN.md currently has no way to express motion — duration, easing, transitions — which means agents generating code have to invent defaults every time. Proposing a motion: frontmatter block and a ## Motion markdown section.

Precedent

  • W3C DTCG 2025.10 does not cover motion tokens (confirmed by reading the current draft)
  • Material Design 3 ships duration + easing tokens (md.motion.duration.short1 = 50ms, etc.)
  • IBM Carbon, Fluent UI, Shopify Polaris all publish motion tokens
  • Radix UI and Tailwind ship motion utilities but no formal tokens
  • Missing link: a format that lets a design system publish motion tokens as first-class entries that an agent or exporter can read

Proposed schema

motion:
  duration:
    fast: 150ms
    medium: 300ms
    slow: 600ms
  easing:
    standard:    "cubic-bezier(0.2, 0, 0, 1)"
    emphasized:  "cubic-bezier(0.2, 0, 0, 1.5)"
    decelerate:  "cubic-bezier(0, 0, 0, 1)"
  prefers-reduced-motion-fallback:
    medium: 100ms    # 300ms collapses to 100ms
    slow:   100ms    # 600ms collapses to 100ms

Parallel to existing spacing / rounded maps. Values are CSS-native (ms/s for duration, cubic-bezier(…) or named keyword for easing).

Proposed lint rule

motion-reduce-compat — warn when a duration exceeds 200ms and no matching key exists in prefers-reduced-motion-fallback. Rationale: animations longer than roughly 200ms register as deliberate motion (rather than state transitions), which WCAG 2.2 + vestibular-sensitivity guidance says needs a reduced-motion path.

Severity: warning. Authors who intentionally ship long animations without a fallback (brand showcase, hero, etc.) acknowledge the warning explicitly.

Implementation notes

Built and verified in our @google/design.md bridge:

  • motion.ts ~100 lines — parse, validate
  • test-motion.ts 27/27 passing
  • Integrates cleanly as an additive motion: key (Google's parser silently drops unknown frontmatter keys, so this is backward-compatible with v0.1.1 until the spec lands)

Happy to PR either as:

  1. Spec-only (just adopt the schema into docs/spec.md)
  2. Spec + linter rule (adds the rule to DEFAULT_RULES)
  3. Spec + linter + exporter (Tailwind config theme.transitionDuration + theme.transitionTimingFunction)

Prior art for reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions