Files
Claude-Code-Workflow/.claude/commands/workflow/ui-design/animation-extract.md
catlog22 920b179440 docs: 更新所有命令描述并重新生成索引文件
- 更新所有69个命令文件的description字段,基于实际功能重新生成详细描述
- 重新生成5个索引文件(all-commands, by-category, by-use-case, essential-commands, command-relationships)
- 移动analyze_commands.py到scripts/目录并完善功能
- 移除临时备份文件

命令描述改进示例:
- workflow:plan: 增加了工具和代理的详细说明(Gemini, action-planning-agent)
- cli:execute: 说明了YOLO权限和多种执行模式
- memory:update-related: 详细说明了批处理策略和工具回退链

索引文件改进:
- usage_scenario从2种扩展到10种(更精细分类)
- command-relationships覆盖所有69个命令
- 区分built-in(内置调用)和sequential(用户顺序执行)关系

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 15:11:31 +08:00

912 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: animation-extract
description: Extract animation and transition patterns from URLs, CSS, or interactive questioning for design system documentation
argument-hint: "[--base-path <path>] [--session <id>] [--urls "<list>"] [--mode <auto|interactive>] [--focus "<types>"]"
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
```bash
# 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
```bash
# 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
```bash
# 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)
```bash
# 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
```bash
# 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: Generate Animation Questions (Main Flow)
```bash
# If extraction failed or insufficient, use interactive questioning
IF extraction_insufficient OR extraction_mode == "interactive":
REPORT: "🤔 Interactive animation specification mode"
REPORT: " Context: {has_design_context ? 'Aligning with design tokens' : 'Standalone animation system'}"
REPORT: " Focus: {focus_types}"
# Determine question categories based on focus_types
question_categories = []
IF "all" IN focus_types OR "transitions" IN focus_types:
question_categories.append("timing_scale")
question_categories.append("easing_philosophy")
IF "all" IN focus_types OR "interactions" IN focus_types OR "hover" IN focus_types:
question_categories.append("button_interactions")
question_categories.append("card_interactions")
question_categories.append("input_interactions")
IF "all" IN focus_types OR "page" IN focus_types:
question_categories.append("page_transitions")
IF "all" IN focus_types OR "loading" IN focus_types:
question_categories.append("loading_states")
IF "all" IN focus_types OR "scroll" IN focus_types:
question_categories.append("scroll_animations")
```
### Step 3: Output Questions in Text Format (Main Flow)
```markdown
# Generate and output structured questions
REPORT: ""
REPORT: "===== 动画规格交互式配置 ====="
REPORT: ""
question_number = 1
questions_output = []
# Q1: Timing Scale (if included)
IF "timing_scale" IN question_categories:
REPORT: "【问题{question_number} - 时间尺度】您的设计需要什么样的过渡速度?"
REPORT: "a) 快速敏捷"
REPORT: " 说明100-200ms 过渡,适合工具型应用和即时反馈场景"
REPORT: "b) 平衡适中"
REPORT: " 说明200-400ms 过渡,通用选择,符合多数用户预期"
REPORT: "c) 流畅舒缓"
REPORT: " 说明400-600ms 过渡,适合品牌展示和沉浸式体验"
REPORT: "d) 自定义"
REPORT: " 说明:需要指定具体数值和使用场景"
REPORT: ""
questions_output.append({id: question_number, category: "timing_scale", options: ["a", "b", "c", "d"]})
question_number += 1
# Q2: Easing Philosophy (if included)
IF "easing_philosophy" IN question_categories:
REPORT: "【问题{question_number} - 缓动风格】哪种缓动曲线符合您的品牌调性?"
REPORT: "a) 线性匀速"
REPORT: " 说明:恒定速度,技术感和精确性,适合数据可视化"
REPORT: "b) 快入慢出"
REPORT: " 说明:快速启动自然减速,最接近物理世界,通用推荐"
REPORT: "c) 慢入慢出"
REPORT: " 说明:平滑对称,精致优雅,适合高端品牌"
REPORT: "d) 弹性效果"
REPORT: " 说明Spring/Bounce 回弹,活泼现代,适合互动性强的应用"
REPORT: ""
questions_output.append({id: question_number, category: "easing_philosophy", options: ["a", "b", "c", "d"]})
question_number += 1
# Q3-5: Interaction Animations (button, card, input - if included)
IF "button_interactions" IN question_categories:
REPORT: "【问题{question_number} - 按钮交互】按钮悬停/点击时如何反馈?"
REPORT: "a) 微妙变化"
REPORT: " 说明:仅颜色/透明度变化,适合简约设计"
REPORT: "b) 抬升效果"
REPORT: " 说明:轻微缩放+阴影加深,增强物理感知"
REPORT: "c) 滑动移位"
REPORT: " 说明Transform translateY视觉引导明显"
REPORT: "d) 无动画"
REPORT: " 说明:静态交互,性能优先或特定品牌要求"
REPORT: ""
questions_output.append({id: question_number, category: "button_interactions", options: ["a", "b", "c", "d"]})
question_number += 1
IF "card_interactions" IN question_categories:
REPORT: "【问题{question_number} - 卡片交互】卡片悬停时的动画效果?"
REPORT: "a) 阴影加深"
REPORT: " 说明Box-shadow 变化,层次感增强"
REPORT: "b) 上浮效果"
REPORT: " 说明Transform translateY(-4px),明显的空间层次"
REPORT: "c) 缩放放大"
REPORT: " 说明Scale(1.02),突出焦点内容"
REPORT: "d) 无动画"
REPORT: " 说明:静态卡片,性能或设计考量"
REPORT: ""
questions_output.append({id: question_number, category: "card_interactions", options: ["a", "b", "c", "d"]})
question_number += 1
IF "input_interactions" IN question_categories:
REPORT: "【问题{question_number} - 表单交互】输入框是否需要微交互反馈?"
REPORT: "a) 聚焦动画"
REPORT: " 说明:边框/阴影过渡,清晰的状态指示"
REPORT: "b) 错误抖动"
REPORT: " 说明水平shake动画错误提示更明显"
REPORT: "c) 成功勾选"
REPORT: " 说明Checkmark 动画,完成反馈"
REPORT: "d) 全部包含"
REPORT: " 说明:聚焦+错误+成功的完整反馈体系"
REPORT: "e) 无微交互"
REPORT: " 说明:标准表单,无额外动画"
REPORT: ""
questions_output.append({id: question_number, category: "input_interactions", options: ["a", "b", "c", "d", "e"]})
question_number += 1
# Q6: Page Transitions (if included)
IF "page_transitions" IN question_categories:
REPORT: "【问题{question_number} - 页面过渡】页面/路由切换是否需要过渡动画?"
REPORT: "a) 淡入淡出"
REPORT: " 说明Crossfade 效果,平滑过渡不突兀"
REPORT: "b) 滑动切换"
REPORT: " 说明Swipe left/right方向性导航"
REPORT: "c) 缩放过渡"
REPORT: " 说明Scale in/out空间层次感"
REPORT: "d) 无过渡"
REPORT: " 说明:即时切换,性能优先"
REPORT: ""
questions_output.append({id: question_number, category: "page_transitions", options: ["a", "b", "c", "d"]})
question_number += 1
# Q7: Loading States (if included)
IF "loading_states" IN question_categories:
REPORT: "【问题{question_number} - 加载状态】加载时使用何种动画风格?"
REPORT: "a) 旋转加载器"
REPORT: " 说明Spinner 圆形旋转,通用加载指示"
REPORT: "b) 脉冲闪烁"
REPORT: " 说明Opacity pulse轻量级反馈"
REPORT: "c) 骨架屏"
REPORT: " 说明Shimmer effect内容占位预览"
REPORT: "d) 进度条"
REPORT: " 说明Linear fill进度量化展示"
REPORT: ""
questions_output.append({id: question_number, category: "loading_states", options: ["a", "b", "c", "d"]})
question_number += 1
# Q8: Scroll Animations (if included)
IF "scroll_animations" IN question_categories:
REPORT: "【问题{question_number} - 滚动动画】元素是否在滚动时触发动画?"
REPORT: "a) 淡入出现"
REPORT: " 说明Opacity 0→1渐进式内容呈现"
REPORT: "b) 上滑出现"
REPORT: " 说明TranslateY + fade方向性引导"
REPORT: "c) 缩放淡入"
REPORT: " 说明Scale 0.9→1 + fade聚焦效果"
REPORT: "d) 交错延迟"
REPORT: " 说明Stagger 序列动画,列表渐次呈现"
REPORT: "e) 无滚动动画"
REPORT: " 说明:静态内容,性能或可访问性考量"
REPORT: ""
questions_output.append({id: question_number, category: "scroll_animations", options: ["a", "b", "c", "d", "e"]})
question_number += 1
REPORT: "支持格式:"
REPORT: "- 空格分隔1a 2b 3c"
REPORT: "- 逗号分隔1a,2b,3c"
REPORT: "- 自由组合1a 2b,3c"
REPORT: ""
REPORT: "请输入您的选择:"
```
### Step 4: Wait for User Input (Main Flow)
```javascript
# Wait for user input
user_raw_input = WAIT_FOR_USER_INPUT()
# Store raw input for debugging
REPORT: "收到输入: {user_raw_input}"
```
### Step 5: Parse User Answers (Main Flow)
```javascript
# Intelligent input parsing (support multiple formats)
answers = {}
# Parse input using intelligent matching
# Support formats: "1a 2b 3c", "1a,2b,3c", "1a 2b,3c"
parsed_responses = PARSE_USER_INPUT(user_raw_input, questions_output)
# Validate parsing
IF parsed_responses.is_valid:
# Map question numbers to categories
FOR response IN parsed_responses.answers:
question_id = response.question_id
selected_option = response.option
# Find category for this question
FOR question IN questions_output:
IF question.id == question_id:
category = question.category
answers[category] = selected_option
REPORT: "✅ 问题{question_id} ({category}): 选择 {selected_option}"
break
ELSE:
REPORT: "❌ 输入格式无法识别,请参考格式示例重新输入:"
REPORT: " 示例1a 2b 3c 4d"
# Return to Step 3 for re-input
GOTO Step 3
```
### Step 6: Write Animation Specification (Main Flow)
```javascript
# Map user choices to specification structure
specification = {
"metadata": {
"source": "interactive",
"timestamp": NOW(),
"focus_types": focus_types,
"has_design_context": has_design_context
},
"timing_scale": MAP_TIMING_SCALE(answers.timing_scale),
"easing_philosophy": MAP_EASING_PHILOSOPHY(answers.easing_philosophy),
"interactions": {
"button": MAP_BUTTON_INTERACTION(answers.button_interactions),
"card": MAP_CARD_INTERACTION(answers.card_interactions),
"input": MAP_INPUT_INTERACTION(answers.input_interactions)
},
"page_transitions": MAP_PAGE_TRANSITIONS(answers.page_transitions),
"loading_animations": MAP_LOADING_STATES(answers.loading_states),
"scroll_animations": MAP_SCROLL_ANIMATIONS(answers.scroll_animations)
}
# Mapping functions (inline logic)
FUNCTION MAP_TIMING_SCALE(option):
SWITCH option:
CASE "a": RETURN {scale: "fast", base_duration: "150ms", range: "100-200ms"}
CASE "b": RETURN {scale: "balanced", base_duration: "300ms", range: "200-400ms"}
CASE "c": RETURN {scale: "smooth", base_duration: "500ms", range: "400-600ms"}
CASE "d": RETURN {scale: "custom", base_duration: "300ms", note: "User to provide values"}
FUNCTION MAP_EASING_PHILOSOPHY(option):
SWITCH option:
CASE "a": RETURN {style: "linear", curve: "linear"}
CASE "b": RETURN {style: "ease-out", curve: "cubic-bezier(0, 0, 0.2, 1)"}
CASE "c": RETURN {style: "ease-in-out", curve: "cubic-bezier(0.4, 0, 0.2, 1)"}
CASE "d": RETURN {style: "spring", curve: "cubic-bezier(0.34, 1.56, 0.64, 1)"}
FUNCTION MAP_BUTTON_INTERACTION(option):
SWITCH option:
CASE "a": RETURN {type: "subtle", properties: ["color", "background-color", "opacity"]}
CASE "b": RETURN {type: "lift", properties: ["transform", "box-shadow"], transform: "scale(1.02)"}
CASE "c": RETURN {type: "slide", properties: ["transform"], transform: "translateY(-2px)"}
CASE "d": RETURN {type: "none", properties: []}
FUNCTION MAP_CARD_INTERACTION(option):
SWITCH option:
CASE "a": RETURN {type: "shadow", properties: ["box-shadow"]}
CASE "b": RETURN {type: "float", properties: ["transform", "box-shadow"], transform: "translateY(-4px)"}
CASE "c": RETURN {type: "scale", properties: ["transform"], transform: "scale(1.02)"}
CASE "d": RETURN {type: "none", properties: []}
FUNCTION MAP_INPUT_INTERACTION(option):
SWITCH option:
CASE "a": RETURN {enabled: ["focus"], focus: {properties: ["border-color", "box-shadow"]}}
CASE "b": RETURN {enabled: ["error"], error: {animation: "shake", keyframes: "translateX"}}
CASE "c": RETURN {enabled: ["success"], success: {animation: "checkmark", keyframes: "draw"}}
CASE "d": RETURN {enabled: ["focus", "error", "success"]}
CASE "e": RETURN {enabled: []}
FUNCTION MAP_PAGE_TRANSITIONS(option):
SWITCH option:
CASE "a": RETURN {enabled: true, style: "fade", animation: "fadeIn/fadeOut"}
CASE "b": RETURN {enabled: true, style: "slide", animation: "slideLeft/slideRight"}
CASE "c": RETURN {enabled: true, style: "zoom", animation: "zoomIn/zoomOut"}
CASE "d": RETURN {enabled: false}
FUNCTION MAP_LOADING_STATES(option):
SWITCH option:
CASE "a": RETURN {style: "spinner", animation: "rotate", keyframes: "360deg"}
CASE "b": RETURN {style: "pulse", animation: "pulse", keyframes: "opacity"}
CASE "c": RETURN {style: "skeleton", animation: "shimmer", keyframes: "gradient-shift"}
CASE "d": RETURN {style: "progress", animation: "fill", keyframes: "width"}
FUNCTION MAP_SCROLL_ANIMATIONS(option):
SWITCH option:
CASE "a": RETURN {enabled: true, style: "fade", animation: "fadeIn"}
CASE "b": RETURN {enabled: true, style: "slideUp", animation: "slideUp", transform: "translateY(20px)"}
CASE "c": RETURN {enabled: true, style: "scaleIn", animation: "scaleIn", transform: "scale(0.9)"}
CASE "d": RETURN {enabled: true, style: "stagger", animation: "fadeIn", stagger_delay: "100ms"}
CASE "e": RETURN {enabled: false}
# Write specification file
output_path = "{base_path}/.intermediates/animation-analysis/animation-specification.json"
Write(output_path, JSON.stringify(specification, indent=2))
REPORT: "✅ Animation specification saved to {output_path}"
REPORT: " Proceeding to token synthesis..."
```
---
**Phase 2 Output**: `animation-specification.json` (user preferences)
## Phase 3: Animation Token Synthesis (Agent - No User Interaction)
**Executor**: `Task(ui-design-agent)` for token generation
**⚠️ CRITICAL**: This phase has NO user interaction. Agent only reads existing data and generates tokens.
### Step 1: Load All Input Sources
```bash
# 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)
REPORT: "✅ Loaded user specification from Phase 2"
ELSE:
REPORT: "⚠️ No user specification found - using extracted CSS only"
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 (Pure Synthesis)
```javascript
Task(ui-design-agent): `
[ANIMATION_TOKEN_GENERATION_TASK]
Synthesize animation data into production-ready tokens - NO user interaction
SESSION: {session_id} | BASE_PATH: {base_path}
## ⚠️ CRITICAL: Pure Synthesis Task
- NO user questions or interaction
- READ existing specification files ONLY
- Generate tokens based on available data
## Input Sources (Read-Only)
1. **Extracted CSS Animations** (if available):
${extracted_animations.length > 0 ? JSON.stringify(extracted_animations) : "None - skip CSS data"}
2. **User Specification** (REQUIRED if Phase 2 ran):
File: {base_path}/.intermediates/animation-analysis/animation-specification.json
${user_specification ? "Status: ✅ Found - READ this file for user choices" : "Status: ⚠️ Not found - use CSS extraction only"}
3. **Design Tokens Context** (for alignment):
${design_tokens ? JSON.stringify(design_tokens) : "None - standalone animation system"}
## Synthesis Rules
### Priority System
1. User specification from animation-specification.json (highest priority)
2. Extracted CSS values from animations-*.json (medium priority)
3. Industry best practices (fallback)
### Duration Normalization
- IF user_specification.timing_scale EXISTS:
Use user's chosen scale (fast/balanced/smooth/custom)
- ELSE IF extracted CSS durations available:
Cluster extracted durations into 3-5 semantic scales
- ELSE:
Use standard scale (instant:0ms, fast:150ms, normal:300ms, slow:500ms, very-slow:800ms)
- Align with design token spacing scale if available
### Easing Standardization
- IF user_specification.easing_philosophy EXISTS:
Use user's chosen philosophy (linear/ease-out/ease-in-out/spring)
- ELSE IF extracted CSS easings available:
Identify common easing functions from CSS
- ELSE:
Use standard easings
- Map to semantic names and convert to cubic-bezier format
### Animation Categorization
Organize into:
- **duration**: Timing scale (instant, fast, normal, slow, very-slow)
- **easing**: Easing functions (linear, ease-in, ease-out, ease-in-out, spring)
- **transitions**: Property-specific transitions (color, transform, opacity, etc.)
- **keyframes**: Named @keyframe animations (fadeIn, slideInUp, pulse, etc.)
- **interactions**: Interaction-specific presets (button-hover, card-hover, input-focus, etc.)
- **page_transitions**: Route/view change animations (if user enabled)
- **scroll_animations**: Scroll-triggered animations (if user enabled)
### User Specification Integration
IF user_specification EXISTS:
- Map user choices to token values:
* timing_scale → duration values
* easing_philosophy → easing curves
* interactions.button → interactions.button-hover token
* interactions.card → interactions.card-hover token
* interactions.input → micro-interaction tokens
* page_transitions → page_transitions tokens
* loading_animations → loading state tokens
* scroll_animations → scroll_animations tokens
## Generate Files
### 1. animation-tokens.json
Complete animation token structure using var() references:
{
"duration": {
"instant": "0ms",
"fast": "150ms", # Adjust based on user_specification.timing_scale
"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)", # Adjust based on user_specification.easing_philosophy
"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"}},
# Add more keyframes based on user_specification choices
},
"interactions": {
"button-hover": {
# Map from user_specification.interactions.button
"properties": ["background-color", "transform"],
"duration": "var(--duration-fast)",
"easing": "var(--easing-ease-out)",
"transform": "scale(1.02)"
},
"card-hover": {
# Map from user_specification.interactions.card
"properties": ["box-shadow", "transform"],
"duration": "var(--duration-normal)",
"easing": "var(--easing-ease-out)",
"transform": "translateY(-4px)"
}
# Add input-focus, modal-open, dropdown-toggle based on user choices
},
"page_transitions": {
# IF user_specification.page_transitions.enabled == true
"fade": {
"duration": "var(--duration-normal)",
"enter": "fadeIn",
"exit": "fadeOut"
}
# Add slide, zoom based on user_specification.page_transitions.style
},
"scroll_animations": {
# IF user_specification.scroll_animations.enabled == true
"default": {
"animation": "fadeIn", # From user_specification.scroll_animations.style
"duration": "var(--duration-slow)",
"easing": "var(--easing-ease-out)",
"threshold": "0.1",
"stagger_delay": "100ms" # From user_specification if stagger chosen
}
}
}
### 2. animation-guide.md
Comprehensive usage guide with sections:
- **Animation Philosophy**: Rationale from user choices and CSS analysis
- **Duration Scale**: Explanation of timing values and usage contexts
- **Easing Functions**: When to use each easing curve
- **Transition Presets**: Property-specific transition guidelines
- **Keyframe Animations**: Available animations and use cases
- **Interaction Patterns**: Button, card, input animation examples
- **Page Transitions**: Route change animation implementation (if enabled)
- **Scroll Animations**: Scroll-trigger setup and configuration (if enabled)
- **Implementation Examples**: CSS and JavaScript code samples
- **Accessibility**: prefers-reduced-motion media query setup
- **Performance Best Practices**: Hardware acceleration, will-change usage
## Output File Paths
- animation-tokens.json: {base_path}/animation-extraction/animation-tokens.json
- animation-guide.md: {base_path}/animation-extraction/animation-guide.md
## Critical Requirements
- ✅ READ animation-specification.json if it exists (from Phase 2)
- ✅ Use Write() tool immediately for both files
- ✅ All tokens use CSS Custom Property format: var(--duration-fast)
- ✅ Include prefers-reduced-motion media query guidance
- ✅ Validate all cubic-bezier values are valid (4 numbers between 0-1)
- ❌ NO user questions or interaction in this phase
- ❌ NO external research or MCP calls
`
```
---
**Phase 3 Output**: `animation-tokens.json` + `animation-guide.md`
## Phase 4: Verify Output
### Step 1: Check Files Created
```bash
# 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
bash(ls -lh {base_path}/animation-extraction/)
```
**Output**: 2 files verified (animation-tokens.json, animation-guide.md)
## Completion
### Todo Update
```javascript
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 (main flow)", status: "completed", activeForm: "Collecting user input in main flow"},
{content: "Animation token synthesis (agent - no interaction)", status: "completed", activeForm: "Generating tokens via agent"},
{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 (main flow)
}
{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
```bash
# 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
```bash
# 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
```bash
# 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
```json
{
"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
- **Main Flow Interaction** - User questions in main flow, agent only for token synthesis
- **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
- **Separated Concerns** - User decisions (Phase 2 main flow) → Token generation (Phase 3 agent)
## Integration
**Workflow Position**: Between style extraction and layout extraction (or parallel)
**New Workflow**:
1. `/workflow:ui-design:style-extract``design-tokens.json` + `style-guide.md`
2. **`/workflow:ui-design:animation-extract`** → `animation-tokens.json` + `animation-guide.md` (NEW)
3. `/workflow:ui-design:layout-extract``layout-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.