Files
Claude-Code-Workflow/.claude/commands/workflow/ui-design/animation-extract.md
catlog22 80196cc0a0 feat: integrate animation token system into UI workflow
Fixes critical P0 issue where animation-tokens.json wasn't consumed by the
generate command, breaking the value chain. The animation extraction system
now properly flows through: animation-extract → tokens → generate → prototypes.

Changes:
- Added animation-extract command with hybrid CSS extraction + interactive
  fallback strategy
- Updated generate.md to load and inject animation tokens into prototypes
- Added CSS animation support (custom properties, keyframes, interactions,
  accessibility)
- Integrated animation extraction into explore-auto and imitate-auto workflows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 11:01:22 +08:00

22 KiB

name: animation-extract description: Extract animation and transition patterns from URLs, CSS, or interactive questioning argument-hint: "[--base-path ] [--session ] [--urls ""] [--mode <auto|interactive>] [--focus ""]" allowed-tools: TodoWrite(), Read(), Write(), Glob(), Bash(), Task(ui-design-agent), mcp__chrome-devtools__navigate_page(), mcp__chrome-devtools__evaluate_script(*)

Animation Extraction Command

Overview

Extract animation and transition patterns from web pages using CSS extraction, visual analysis, or interactive questioning. This command generates production-ready animation tokens and guidelines that integrate with design systems.

Strategy: Hybrid Extraction with Interactive Fallback

  • Auto Mode (Priority 1): Extract from CSS via Chrome DevTools when URLs provided
  • Visual Mode (Priority 2): Analyze screenshots for motion cues (blur, position changes)
  • Interactive Mode (Priority 3): Guided questioning when extraction insufficient
  • Output: animation-tokens.json + animation-guide.md

Phase 0: Setup & Input Validation

Step 1: Detect Input Mode & Base Path

# Detect input source
# Priority: --urls → url mode | --mode interactive → question mode

# Parse URLs if provided (format: "target:url,target:url,...")
IF --urls:
    url_list = []
    FOR pair IN split(--urls, ","):
        IF ":" IN pair:
            target, url = pair.split(":", 1)
            url_list.append({target: target.strip(), url: url.strip()})
        ELSE:
            url_list.append({target: "page", url: pair.strip()})

    has_urls = true
    primary_url = url_list[0].url
ELSE:
    has_urls = false

# Determine extraction mode
extraction_mode = --mode OR (has_urls ? "auto" : "interactive")

# Parse animation focus (if provided)
IF --focus:
    focus_types = split(--focus, ",")  # e.g., "transitions,hover,scroll"
ELSE:
    focus_types = ["all"]  # Extract all animation types

# Determine base path
bash(find .workflow -type d -name "design-*" | head -1)  # Auto-detect
# OR use --base-path / --session parameters

Step 2: Load Design Tokens Context

# Load existing design tokens for duration/easing alignment
IF exists({base_path}/style-extraction/style-1/design-tokens.json):
    design_tokens = Read({base_path}/style-extraction/style-1/design-tokens.json)
    has_design_context = true
ELSE:
    has_design_context = false
    WARN: "⚠️ No design tokens found - animation tokens will use standalone values"

# Create output directory
bash(mkdir -p {base_path}/animation-extraction)
bash(mkdir -p {base_path}/.intermediates/animation-analysis)

Phase 0 Output: extraction_mode, base_path, has_urls, url_list[], focus_types[], has_design_context

Phase 1: CSS Animation Extraction (Auto Mode - URL Required)

Step 1: Check Extraction Mode

# extraction_mode == "interactive" → skip to Phase 2
# extraction_mode == "auto" AND has_urls → execute this phase

If interactive mode: Skip to Phase 2

Step 2: Extract Computed Animations (Auto-Trigger)

# AUTO-TRIGGER: If URLs are available, automatically extract CSS animations/transitions

IF has_urls AND mcp_chrome_devtools_available:
    REPORT: "🔍 Auto-triggering URL mode: Extracting CSS animations and transitions"

    # Read extraction script
    script_content = Read(~/.claude/scripts/extract-animations.js)

    # For each URL:
    FOR url_info IN url_list:
        target = url_info.target
        url = url_info.url

        REPORT: "   Processing: {target} ({url})"

        # Open page in Chrome DevTools
        mcp__chrome-devtools__navigate_page(url=url)

        # Wait for page to fully load and animations to initialize
        bash(sleep 2)

        # Execute extraction script
        result = mcp__chrome-devtools__evaluate_script(function=script_content)

        # Save raw animation data
        Write({base_path}/.intermediates/animation-analysis/animations-{target}.json, result)

        REPORT: "   ✅ Extracted: {result.summary.total_animations} animations, {result.summary.total_transitions} transitions"

    animations_extracted = true
    REPORT: "   ✅ CSS animation extraction complete"
ELSE IF has_urls AND NOT mcp_chrome_devtools_available:
    animations_extracted = false
    REPORT: "⚠️ Chrome DevTools MCP not available"
    REPORT: "   Falling back to interactive mode for animation guidance"
ELSE:
    animations_extracted = false

Extraction Script Reference: ~/.claude/scripts/extract-animations.js

Usage: Read the script file and use content directly in mcp__chrome-devtools__evaluate_script()

Script returns:

  • metadata: Extraction timestamp, URL, method
  • transitions: Array of transition definitions (property, duration, easing, delay)
  • animations: Array of keyframe animations (name, duration, easing, keyframes)
  • transforms: Common transform patterns
  • summary: Statistics (total_animations, total_transitions, unique_easings)

Benefits:

  • Real animation values from production sites
  • Captures all CSS transitions and @keyframes rules
  • Identifies common easing functions and durations
  • Maps animations to element selectors

Phase 1 Output: animations-{target}.json (intermediate files)

Phase 2: Interactive Animation Specification (Interactive/Fallback Mode)

Step 1: Check if Extraction Sufficient

# If animations extracted from CSS, check coverage
IF animations_extracted:
    total_animations = sum([data.summary.total_animations for data in all_extracted])
    total_transitions = sum([data.summary.total_transitions for data in all_extracted])

    # If sufficient data found, skip interactive mode
    IF total_animations >= 3 OR total_transitions >= 5:
        REPORT: "✅ Sufficient animation data extracted from CSS"
        SKIP to Phase 3
    ELSE:
        REPORT: "⚠️ Limited animation data found - launching interactive mode"
        extraction_insufficient = true
ELSE:
    extraction_insufficient = true

Step 2: Interactive Question Workflow (Agent)

# If extraction failed or insufficient, use interactive questioning
IF extraction_insufficient OR extraction_mode == "interactive":
    REPORT: "🤔 Launching interactive animation specification mode"

    # Launch ui-design-agent for interactive questioning
    Task(ui-design-agent): `
      [ANIMATION_SPECIFICATION_TASK]
      Guide user through animation design decisions via structured questions

      SESSION: {session_id} | MODE: interactive | BASE_PATH: {base_path}

      ## Context
      - Design tokens available: {has_design_context}
      - Focus areas: {focus_types}
      - Extracted data: {animations_extracted ? "Partial CSS data available" : "No CSS data"}

      ## Interactive Workflow

      For each animation category, ASK user and WAIT for response:

      ### 1. Transition Duration Scale
      QUESTION: "What timing scale feels right for your design?"
      OPTIONS:
        - "Fast & Snappy" (100-200ms transitions)
        - "Balanced" (200-400ms transitions)
        - "Smooth & Deliberate" (400-600ms transitions)
        - "Custom" (specify values)

      ### 2. Easing Philosophy
      QUESTION: "What easing style matches your brand?"
      OPTIONS:
        - "Linear" (constant speed, technical feel)
        - "Ease-Out" (fast start, natural feel)
        - "Ease-In-Out" (balanced, polished feel)
        - "Spring/Bounce" (playful, modern feel)
        - "Custom" (specify cubic-bezier)

      ### 3. Common Interactions (Ask for each)
      FOR interaction IN ["button-hover", "link-hover", "card-hover", "modal-open", "dropdown-toggle"]:
        QUESTION: "How should {interaction} animate?"
        OPTIONS:
          - "Subtle" (color/opacity change only)
          - "Lift" (scale + shadow increase)
          - "Slide" (transform translateY)
          - "Fade" (opacity transition)
          - "None" (no animation)
          - "Custom" (describe behavior)

      ### 4. Page Transitions
      QUESTION: "Should page/route changes have animations?"
      IF YES:
        ASK: "What style?"
        OPTIONS:
          - "Fade" (crossfade between views)
          - "Slide" (swipe left/right)
          - "Zoom" (scale in/out)
          - "None"

      ### 5. Loading States
      QUESTION: "What loading animation style?"
      OPTIONS:
        - "Spinner" (rotating circle)
        - "Pulse" (opacity pulse)
        - "Skeleton" (shimmer effect)
        - "Progress Bar" (linear fill)
        - "Custom" (describe)

      ### 6. Micro-interactions
      QUESTION: "Should form inputs have micro-interactions?"
      IF YES:
        ASK: "What interactions?"
        OPTIONS:
          - "Focus state animation" (border/shadow transition)
          - "Error shake" (horizontal shake on error)
          - "Success check" (checkmark animation)
          - "All of the above"

      ### 7. Scroll Animations
      QUESTION: "Should elements animate on scroll?"
      IF YES:
        ASK: "What scroll animation style?"
        OPTIONS:
          - "Fade In" (opacity 0→1)
          - "Slide Up" (translateY + fade)
          - "Scale In" (scale 0.9→1 + fade)
          - "Stagger" (sequential delays)
          - "None"

      ## Output Generation

      Based on user responses, generate structured data:

      1. Create animation-specification.json with user choices:
         - timing_scale (fast/balanced/slow/custom)
         - easing_philosophy (linear/ease-out/ease-in-out/spring)
         - interactions: {interaction_name: {type, properties, timing}}
         - page_transitions: {enabled, style, duration}
         - loading_animations: {style, duration}
         - scroll_animations: {enabled, style, stagger_delay}

      2. Write to {base_path}/.intermediates/animation-analysis/animation-specification.json

      ## Critical Requirements
      - ✅ Use Write() tool immediately for specification file
      - ✅ Wait for user response after EACH question before proceeding
      - ✅ Validate responses and ask for clarification if needed
      - ✅ Provide sensible defaults if user skips questions
      - ❌ NO external research or MCP calls
    `

Phase 2 Output: animation-specification.json (user preferences)

Phase 3: Animation Token Synthesis (Agent)

Executor: Task(ui-design-agent) for token generation

Step 1: Load All Input Sources

# Gather all available animation data
extracted_animations = []
IF animations_extracted:
    FOR target IN target_list:
        IF exists({base_path}/.intermediates/animation-analysis/animations-{target}.json):
            extracted_animations.append(Read(file))

user_specification = null
IF exists({base_path}/.intermediates/animation-analysis/animation-specification.json):
    user_specification = Read(file)

design_tokens = null
IF has_design_context:
    design_tokens = Read({base_path}/style-extraction/style-1/design-tokens.json)

Step 2: Launch Token Generation Task

Task(ui-design-agent): `
  [ANIMATION_TOKEN_GENERATION_TASK]
  Synthesize all animation data into production-ready animation tokens

  SESSION: {session_id} | BASE_PATH: {base_path}

  ## Input Sources
  1. Extracted CSS Animations: {JSON.stringify(extracted_animations) OR "None"}
  2. User Specification: {JSON.stringify(user_specification) OR "None"}
  3. Design Tokens Context: {JSON.stringify(design_tokens) OR "None"}

  ## Synthesis Rules

  ### Priority System
  1. User specification (highest priority)
  2. Extracted CSS values (medium priority)
  3. Industry best practices (fallback)

  ### Duration Normalization
  - Analyze all extracted durations
  - Cluster into 3-5 semantic scales: instant, fast, normal, slow, very-slow
  - Align with design token spacing scale if available

  ### Easing Standardization
  - Identify common easing functions from extracted data
  - Map to semantic names: linear, ease-in, ease-out, ease-in-out, spring
  - Convert all cubic-bezier values to standard format

  ### Animation Categorization
  Organize into:
  - transitions: Property-specific transitions (color, transform, opacity)
  - keyframe_animations: Named @keyframe animations
  - interactions: Interaction-specific presets (hover, focus, active)
  - micro_interactions: Small feedback animations
  - page_transitions: Route/view change animations
  - scroll_animations: Scroll-triggered animations

  ## Generate Files

  ### 1. animation-tokens.json
  Complete animation token structure:

  {
    "duration": {
      "instant": "0ms",
      "fast": "150ms",
      "normal": "300ms",
      "slow": "500ms",
      "very-slow": "800ms"
    },
    "easing": {
      "linear": "linear",
      "ease-in": "cubic-bezier(0.4, 0, 1, 1)",
      "ease-out": "cubic-bezier(0, 0, 0.2, 1)",
      "ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
      "spring": "cubic-bezier(0.34, 1.56, 0.64, 1)"
    },
    "transitions": {
      "color": {
        "property": "color, background-color, border-color",
        "duration": "var(--duration-fast)",
        "easing": "var(--easing-ease-out)"
      },
      "transform": {
        "property": "transform",
        "duration": "var(--duration-normal)",
        "easing": "var(--easing-ease-out)"
      },
      "opacity": {
        "property": "opacity",
        "duration": "var(--duration-normal)",
        "easing": "var(--easing-ease-in-out)"
      }
    },
    "keyframes": {
      "fadeIn": {
        "0%": {"opacity": "0"},
        "100%": {"opacity": "1"}
      },
      "slideInUp": {
        "0%": {"transform": "translateY(20px)", "opacity": "0"},
        "100%": {"transform": "translateY(0)", "opacity": "1"}
      },
      "pulse": {
        "0%, 100%": {"opacity": "1"},
        "50%": {"opacity": "0.7"}
      }
    },
    "interactions": {
      "button-hover": {
        "properties": ["background-color", "transform"],
        "duration": "var(--duration-fast)",
        "easing": "var(--easing-ease-out)",
        "transform": "scale(1.02)"
      },
      "card-hover": {
        "properties": ["box-shadow", "transform"],
        "duration": "var(--duration-normal)",
        "easing": "var(--easing-ease-out)",
        "transform": "translateY(-4px)"
      }
    },
    "page_transitions": {
      "fade": {
        "duration": "var(--duration-normal)",
        "enter": "fadeIn",
        "exit": "fadeOut"
      }
    },
    "scroll_animations": {
      "default": {
        "animation": "fadeInUp",
        "duration": "var(--duration-slow)",
        "easing": "var(--easing-ease-out)",
        "threshold": "0.1",
        "stagger_delay": "100ms"
      }
    }
  }

  ### 2. animation-guide.md
  Comprehensive usage guide:
  - Animation philosophy and rationale
  - Duration scale explanation
  - Easing function usage guidelines
  - Interaction animation patterns
  - Implementation examples (CSS and JS)
  - Accessibility considerations (prefers-reduced-motion)
  - Performance best practices

  ## Critical Requirements
  - ✅ Use Write() tool immediately for both files
  - ✅ Ensure all tokens use CSS Custom Property format: var(--duration-fast)
  - ✅ Include prefers-reduced-motion media query guidance
  - ✅ Validate all cubic-bezier values are valid
  - ❌ NO external research or MCP calls
`

Phase 3 Output: animation-tokens.json + animation-guide.md

Phase 4: Verify Output

Step 1: Check Files Created

# Verify animation tokens created
bash(test -f {base_path}/animation-extraction/animation-tokens.json && echo "exists")
bash(test -f {base_path}/animation-extraction/animation-guide.md && echo "exists")

# Validate structure
bash(cat {base_path}/animation-extraction/animation-tokens.json | grep -q "duration" && echo "valid")
bash(cat {base_path}/animation-extraction/animation-tokens.json | grep -q "easing" && echo "valid")

Step 2: Verify File Sizes

bash(ls -lh {base_path}/animation-extraction/)

Output: 2 files verified (animation-tokens.json, animation-guide.md)

Completion

Todo Update

TodoWrite({todos: [
  {content: "Setup and input validation", status: "completed", activeForm: "Validating inputs"},
  {content: "CSS animation extraction (auto mode)", status: "completed", activeForm: "Extracting from CSS"},
  {content: "Interactive specification (fallback)", status: "completed", activeForm: "Collecting user input"},
  {content: "Animation token synthesis (agent)", status: "completed", activeForm: "Generating tokens"},
  {content: "Verify output files", status: "completed", activeForm: "Verifying files"}
]});

Output Message

✅ Animation extraction complete!

Configuration:
- Session: {session_id}
- Extraction Mode: {extraction_mode} (auto/interactive)
- Input Sources:
  {IF animations_extracted:
  - ✅ CSS extracted from {len(url_list)} URL(s)
  }
  {IF user_specification:
  - ✅ User specification via interactive mode
  }
  {IF has_design_context:
  - ✅ Aligned with existing design tokens
  }

Generated Files:
{base_path}/animation-extraction/
├── animation-tokens.json      # Production-ready animation tokens
└── animation-guide.md          # Usage guidelines and examples

{IF animations_extracted:
Intermediate Analysis:
{base_path}/.intermediates/animation-analysis/
├── animations-*.json           # Extracted CSS data ({len(url_list)} files)
}
{IF user_specification:
└── animation-specification.json # User preferences
}

Extracted Data Summary:
- Duration scales: {duration_count} values
- Easing functions: {easing_count} types
- Interaction presets: {interaction_count} patterns
- Keyframe animations: {keyframe_count} animations

Next: Animation tokens ready for integration
  • style-extract/layout-extract can reference animation tokens
  • generate command will include animation CSS
  • Tokens use var() format for easy customization

Simple Bash Commands

Path Operations

# Find design directory
bash(find .workflow -type d -name "design-*" | head -1)

# Create output directories
bash(mkdir -p {base_path}/animation-extraction)
bash(mkdir -p {base_path}/.intermediates/animation-analysis)

Validation Commands

# Check if already extracted
bash(test -f {base_path}/animation-extraction/animation-tokens.json && echo "exists")

# Validate JSON structure
bash(cat {base_path}/animation-extraction/animation-tokens.json | grep -q "duration" && echo "valid")

# Count animation types
bash(cat animation-tokens.json | grep -c "\"keyframes\":")

File Operations

# Load design tokens context
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && cat it)

# Verify output
bash(ls {base_path}/animation-extraction/)

Output Structure

{base_path}/
├── .intermediates/                  # Intermediate analysis files
│   └── animation-analysis/
│       ├── animations-{target}.json      # Extracted CSS (auto mode)
│       └── animation-specification.json  # User input (interactive mode)
└── animation-extraction/            # Final animation tokens
    ├── animation-tokens.json        # Production-ready animation tokens
    └── animation-guide.md            # Usage guide and examples

animation-tokens.json Format

{
  "duration": {
    "instant": "0ms",
    "fast": "150ms",
    "normal": "300ms",
    "slow": "500ms",
    "very-slow": "800ms"
  },
  "easing": {
    "linear": "linear",
    "ease-in": "cubic-bezier(0.4, 0, 1, 1)",
    "ease-out": "cubic-bezier(0, 0, 0.2, 1)",
    "ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
    "spring": "cubic-bezier(0.34, 1.56, 0.64, 1)"
  },
  "transitions": {
    "color": {"property": "...", "duration": "var(--duration-fast)", "easing": "..."},
    "transform": {"property": "...", "duration": "...", "easing": "..."}
  },
  "keyframes": {
    "fadeIn": {"0%": {...}, "100%": {...}},
    "slideInUp": {...}
  },
  "interactions": {
    "button-hover": {"properties": [...], "duration": "...", "transform": "..."},
    "card-hover": {...}
  },
  "page_transitions": {...},
  "scroll_animations": {...}
}

Requirements: CSS var() format, valid cubic-bezier values, prefers-reduced-motion support

Error Handling

Common Errors

ERROR: No URL or interactive mode specified
→ Provide --urls for auto mode or use --mode interactive

ERROR: Chrome DevTools unavailable
→ Automatically falls back to interactive mode

ERROR: Insufficient animation data extracted
→ Launches interactive mode for supplemental input

ERROR: Invalid cubic-bezier values
→ Validates and corrects to nearest standard easing

Recovery Strategies

  • CSS extraction failure: Falls back to interactive mode
  • Partial extraction: Supplements with interactive questioning
  • Invalid data: Validates and uses fallback values

Key Features

  • Auto-Trigger CSS Extraction - Automatically extracts animations when --urls provided
  • Hybrid Strategy - Combines CSS extraction with interactive specification
  • Intelligent Fallback - Gracefully handles extraction failures
  • Context-Aware - Aligns with existing design tokens
  • Production-Ready - CSS var() format, accessibility support
  • Comprehensive Coverage - Transitions, keyframes, interactions, scroll animations
  • Agent-Driven - Autonomous token generation with ui-design-agent

Integration

Workflow Position: Between style extraction and layout extraction (or parallel)

New Workflow:

  1. /workflow:ui-design:style-extractdesign-tokens.json + style-guide.md
  2. /workflow:ui-design:animation-extractanimation-tokens.json + animation-guide.md (NEW)
  3. /workflow:ui-design:layout-extractlayout-templates.json
  4. /workflow:ui-design:generate:
    • Reads: design-tokens.json + animation-tokens.json + layout-templates.json
    • Generates: Prototypes with animation CSS included

Input: URLs (auto mode) or interactive questioning Output: animation-tokens.json + animation-guide.md Next: /workflow:ui-design:layout-extract OR /workflow:ui-design:generate

Note: This command extracts motion design patterns (animations, transitions) to complement visual style tokens. Can run in parallel with layout-extract.