From d213885f5230fb497d5ecc576b43d43d5331851a Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sat, 8 Nov 2025 23:23:06 +0800 Subject: [PATCH] Refactor layout and style extraction workflows for multi-selection capabilities - Updated `layout-extract` command to support user multi-selection of layout concepts, allowing for multiple layout templates to be generated based on user preferences. - Revised argument hints and output structures to reflect changes in selection handling and output file formats. - Enhanced user interaction by enabling multi-select options in both layout and style extraction phases. - Streamlined the generation of layout templates and design systems to accommodate multiple selected variants, improving flexibility and user experience. - Adjusted validation and output verification processes to ensure consistency with new multi-selection features. --- .../workflow/ui-design/batch-generate.md | 33 +- .../workflow/ui-design/explore-auto.md | 38 +- .../workflow/ui-design/imitate-auto.md | 27 +- .../workflow/ui-design/import-from-code.md | 75 +-- .../workflow/ui-design/layout-extract.md | 426 +++++++++--------- .../workflow/ui-design/style-extract.md | 211 ++++----- 6 files changed, 392 insertions(+), 418 deletions(-) diff --git a/.claude/commands/workflow/ui-design/batch-generate.md b/.claude/commands/workflow/ui-design/batch-generate.md index 232d3c03..2122493a 100644 --- a/.claude/commands/workflow/ui-design/batch-generate.md +++ b/.claude/commands/workflow/ui-design/batch-generate.md @@ -70,31 +70,24 @@ IF exists({base_path}/.intermediates/style-analysis/design-space-analysis.json): **Output**: `design_tokens_valid`, `design_space_analysis` -### Step 3: Gather Layout Inspiration (Reuse or Create) +### Step 3: Gather Layout Inspiration (Direct MCP Search) ```bash -# Check if layout inspirations already exist from layout-extract phase -inspiration_source = "{base_path}/.intermediates/layout-analysis/inspirations" +# Gather layout inspiration via MCP for each target +layout_inspiration_map = {} FOR target IN target_list: - # Priority 1: Reuse existing inspiration from layout-extract - IF exists({inspiration_source}/{target}-layout-ideas.txt): - # Reuse existing inspiration (no action needed) - REPORT: "Using existing layout inspiration for {target}" - ELSE: - # Priority 2: Generate new inspiration via MCP - bash(mkdir -p {inspiration_source}) - search_query = "{target} {target_type} layout patterns variations" - mcp__exa__web_search_exa(query=search_query, numResults=5) + search_query = "{target} {target_type} layout patterns variations" + search_results = mcp__exa__web_search_exa(query=search_query, numResults=5) - # Extract context from prompt for this target - target_requirements = extract_relevant_context_from_prompt(prompt_text, target) + # Extract context from prompt for this target + target_requirements = extract_relevant_context_from_prompt(prompt_text, target) - # Write inspiration file to centralized location - Write({inspiration_source}/{target}-layout-ideas.txt, inspiration_content) - REPORT: "Created new layout inspiration for {target}" + # Store inspiration in memory (no file write needed) + layout_inspiration_map[target] = format_inspiration_from_search(search_results, target_requirements) + REPORT: "Gathered layout inspiration for {target}" ``` -**Output**: `T` inspiration text files (reused or created in `.intermediates/layout-analysis/inspirations/`) +**Output**: `layout_inspiration_map` (in-memory, passed to agents) ## Phase 2: Target-Style-Centric Batch Generation (Agent) @@ -132,7 +125,7 @@ Task(ui-design-agent): ` ${design_attributes ? "DESIGN_ATTRIBUTES: " + JSON.stringify(design_attributes) : ""} ## Reference - - Layout inspiration: Read("{base_path}/.intermediates/layout-analysis/inspirations/{target}-layout-ideas.txt") + - Layout inspiration: {layout_inspiration_map[target]} - Design tokens: Read("{base_path}/style-extraction/style-{style_id}/design-tokens.json") Parse ALL token values including: * colors, typography (with combinations), spacing, opacity @@ -315,8 +308,6 @@ bash(~/.claude/scripts/ui-generate-preview.sh "{base_path}/prototypes") {base_path}/ ├── .intermediates/ │ └── layout-analysis/ -│ └── inspirations/ -│ └── {target}-layout-ideas.txt # Layout inspiration (reused or created) ├── prototypes/ │ ├── {target}-style-{s}-layout-{l}.html # Final prototypes │ ├── {target}-style-{s}-layout-{l}.css diff --git a/.claude/commands/workflow/ui-design/explore-auto.md b/.claude/commands/workflow/ui-design/explore-auto.md index 4b48e7c3..e75bbc2a 100644 --- a/.claude/commands/workflow/ui-design/explore-auto.md +++ b/.claude/commands/workflow/ui-design/explore-auto.md @@ -207,7 +207,8 @@ run_id = "run-$(date +%Y%m%d)-$RANDOM" relative_base_path = --session ? ".workflow/WFS-{session}/design-${run_id}" : ".workflow/.design/design-${run_id}" # Create directory and convert to absolute path -Bash(mkdir -p "${relative_base_path}/{style-extraction,prototypes}") +Bash(mkdir -p "${relative_base_path}/style-extraction") +Bash(mkdir -p "${relative_base_path}/prototypes") base_path=$(cd "${relative_base_path}" && pwd) Write({base_path}/.run-metadata.json): { @@ -315,7 +316,8 @@ IF design_source IN ["code_only", "hybrid"]: # Check file existence and assess completeness style_exists = exists("{base_path}/style-extraction/style-1/design-tokens.json") animation_exists = exists("{base_path}/animation-extraction/animation-tokens.json") - layout_exists = exists("{base_path}/layout-extraction/layout-templates.json") + layout_count = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | wc -l) + layout_exists = (layout_count > 0) style_complete = false animation_complete = false @@ -351,14 +353,16 @@ IF design_source IN ["code_only", "hybrid"]: # Layout completeness check IF layout_exists: - layouts = Read("{base_path}/layout-extraction/layout-templates.json") + # Read first layout file to verify structure + first_layout = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | head -1) + layout_data = Read(first_layout) layout_complete = ( - layouts.layout_templates?.length >= 3 && - layouts.extraction_metadata?.layout_system?.type && - layouts.extraction_metadata?.responsive?.breakpoints + layout_count >= 1 && + layout_data.template?.dom_structure && + layout_data.template?.css_layout_rules ) - IF NOT layout_complete AND layouts.extraction_metadata?.completeness?.missing_items: - missing_categories.extend(layouts.extraction_metadata.completeness.missing_items) + IF NOT layout_complete: + missing_categories.push("complete layout structure") ELSE: missing_categories.push("layout templates") @@ -386,7 +390,7 @@ IF design_source == "visual_only" OR needs_visual_supplement: command = "/workflow:ui-design:style-extract --base-path \"{base_path}\" " + (--images ? "--images \"{images}\" " : "") + (--prompt ? "--prompt \"{prompt}\" " : "") + - "--mode explore --variants {style_variants}" + "--variants {style_variants}" SlashCommand(command) ELSE: REPORT: "✅ Phase 1: Style (Using Code Import)" @@ -415,7 +419,7 @@ IF (design_source == "visual_only" OR needs_visual_supplement) OR (NOT layout_co command = "/workflow:ui-design:layout-extract --base-path \"{base_path}\" " + (--images ? "--images \"{images}\" " : "") + (--prompt ? "--prompt \"{prompt}\" " : "") + - "--targets \"{targets_string}\" --mode explore --variants {layout_variants} --device-type \"{device_type}\"" + "--targets \"{targets_string}\" --variants {layout_variants} --device-type \"{device_type}\"" SlashCommand(command) ELSE: REPORT: "✅ Phase 2.5: Layout (Using Code Import)" @@ -549,10 +553,11 @@ Architecture: Style-Centric Batch Generation Run ID: {run_id} | Session: {session_id or "standalone"} Type: {icon} {target_type} | Device: {device_type} | Matrix: {s}×{l}×{n} = {total} prototypes -Phase 1: {s} complete design systems (style-extract) -Phase 2: {n×l} layout templates (layout-extract explore mode) +Phase 1: {s} complete design systems (style-extract with multi-select) +Phase 2: {n×l} layout templates (layout-extract with multi-select) - Device: {device_type} layouts - {n} targets × {l} layout variants = {n×l} structural templates + - User-selected concepts generated in parallel Phase 3: UI Assembly (generate) - Pure assembly: layout templates + design tokens - {s}×{l}×{n} = {total} final prototypes @@ -562,21 +567,22 @@ Phase 4: Brainstorming artifacts updated Assembly Process: ✅ Separation of Concerns: Layout (structure) + Style (tokens) kept separate ✅ Layout Extraction: {n×l} reusable structural templates +✅ Multi-Selection Workflow: User selects multiple variants from generated options ✅ Pure Assembly: No design decisions in generate phase ✅ Device-Optimized: Layouts designed for {device_type} Design Quality: ✅ Token-Driven Styling: 100% var() usage -✅ Structural Variety: {l} distinct layouts per target -✅ Style Variety: {s} independent design systems +✅ Structural Variety: {l} distinct layouts per target (user-selected) +✅ Style Variety: {s} independent design systems (user-selected) ✅ Device-Optimized: Layouts designed for {device_type} 📂 {base_path}/ ├── .intermediates/ (Intermediate analysis files) │ ├── style-analysis/ (computed-styles.json, design-space-analysis.json) - │ └── layout-analysis/ (dom-structure-*.json, inspirations/*.txt) + │ └── layout-analysis/ (analysis-options.json, user-selection.json, dom-structure-*.json) ├── style-extraction/ ({s} complete design systems) - ├── layout-extraction/ ({n×l} layout templates + layout-space-analysis.json) + ├── layout-extraction/ ({n×l} layout template files: layout-{target}-{variant}.json) ├── prototypes/ ({total} assembled prototypes) └── .run-metadata.json (includes device type) diff --git a/.claude/commands/workflow/ui-design/imitate-auto.md b/.claude/commands/workflow/ui-design/imitate-auto.md index 7ce686ec..6a63f65a 100644 --- a/.claude/commands/workflow/ui-design/imitate-auto.md +++ b/.claude/commands/workflow/ui-design/imitate-auto.md @@ -225,8 +225,8 @@ IF design_source == "hybrid": REPORT: " → Source: {code_base_path}" REPORT: " → Mode: Hybrid (Web + Code)" - command = "/workflow:ui-design:import-from-code --base-path \"{base_path}\" " + - "--base-path \"{code_base_path}\"" + command = "/workflow:ui-design:import-from-code --output-path \"{base_path}\" " + + "--source-path \"{code_base_path}\"" TRY: SlashCommand(command) @@ -239,7 +239,8 @@ IF design_source == "hybrid": # Check file existence and assess completeness style_exists = exists("{base_path}/style-extraction/style-1/design-tokens.json") animation_exists = exists("{base_path}/animation-extraction/animation-tokens.json") - layout_exists = exists("{base_path}/layout-extraction/layout-templates.json") + layout_count = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | wc -l) + layout_exists = (layout_count > 0) style_complete = false animation_complete = false @@ -275,14 +276,16 @@ IF design_source == "hybrid": # Layout completeness check IF layout_exists: - layouts = Read("{base_path}/layout-extraction/layout-templates.json") + # Read first layout file to verify structure + first_layout = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | head -1) + layout_data = Read(first_layout) layout_complete = ( - layouts.layout_templates?.length >= 3 && - layouts.extraction_metadata?.layout_system?.type && - layouts.extraction_metadata?.responsive?.breakpoints + layout_count >= 1 && + layout_data.template?.dom_structure && + layout_data.template?.css_layout_rules ) - IF NOT layout_complete AND layouts.extraction_metadata?.completeness?.missing_items: - missing_categories.extend(layouts.extraction_metadata.completeness.missing_items) + IF NOT layout_complete: + missing_categories.push("complete layout structure") ELSE: missing_categories.push("layout templates") @@ -405,7 +408,7 @@ ELSE: extraction_prompt = f"Extract visual style tokens from '{primary_target}' with consistency across all pages." url_map_for_extract = ",".join([f"{name}:{url}" for name, url in url_map.items()]) - extract_command = f"/workflow:ui-design:style-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_extract}\" --prompt \"{extraction_prompt}\" --mode imitate" + extract_command = f"/workflow:ui-design:style-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_extract}\" --prompt \"{extraction_prompt}\" --variants 1" SlashCommand(extract_command) TodoWrite(mark_completed: "Extract style", mark_in_progress: "Extract animation") @@ -436,7 +439,7 @@ IF skip_layout: ELSE: REPORT: "🚀 Phase 2.5: Layout Extraction" url_map_for_layout = ",".join([f"{target}:{url}" for target, url in url_map.items()]) - layout_extract_command = f"/workflow:ui-design:layout-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_layout}\" --targets \"{','.join(target_names)}\" --mode imitate" + layout_extract_command = f"/workflow:ui-design:layout-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_layout}\" --targets \"{','.join(target_names)}\" --variants 1" SlashCommand(layout_extract_command) TodoWrite(mark_completed: "Extract layout", mark_in_progress: "Assemble UI") @@ -546,7 +549,7 @@ ELSE: │ ├── animation-tokens.json │ └── animation-guide.md ├── layout-extraction/ # Structure templates -│ └── layout-templates.json +│ └── layout-{target}-1.json # One file per target └── prototypes/ # {generated_count} HTML/CSS files ├── {target1}-style-1-layout-1.html + .css ├── {target2}-style-1-layout-1.html + .css diff --git a/.claude/commands/workflow/ui-design/import-from-code.md b/.claude/commands/workflow/ui-design/import-from-code.md index 8e5e2dd0..b5d25779 100644 --- a/.claude/commands/workflow/ui-design/import-from-code.md +++ b/.claude/commands/workflow/ui-design/import-from-code.md @@ -1,7 +1,7 @@ --- name: workflow:ui-design:import-from-code description: Import design system from code files (CSS/JS/HTML/SCSS) using parallel agent analysis with final synthesis -argument-hint: "[--base-path ] [--css \"\"] [--js \"\"] [--scss \"\"] [--html \"\"] [--style-files \"\"] [--session ]" +argument-hint: "[--source-path ] [--output-path ] [--css \"\"] [--js \"\"] [--scss \"\"] [--html \"\"] [--style-files \"\"] [--session ]" allowed-tools: Read,Write,Bash,Glob,Grep,Task,TodoWrite auto-continue: true --- @@ -34,7 +34,8 @@ Extract design system tokens from source code files (CSS/SCSS/JS/TS/HTML) using /workflow:ui-design:import-from-code [FLAGS] # Flags ---base-path Base directory for analysis (default: current directory) +--source-path Source code directory to analyze (default: current directory) +--output-path Output directory for extracted design tokens (default: current directory) --css "" CSS file glob pattern (e.g., "theme/*.css") --scss "" SCSS file glob pattern (e.g., "styles/*.scss") --js "" JavaScript file glob pattern (e.g., "theme/*.js") @@ -47,19 +48,19 @@ Extract design system tokens from source code files (CSS/SCSS/JS/TS/HTML) using ```bash # Basic usage - auto-discover all files -/workflow:ui-design:import-from-code --base-path ./ +/workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system # Target specific directories -/workflow:ui-design:import-from-code --base-path ./src --css "theme/*.css" --js "theme/*.js" +/workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system --css "theme/*.css" --js "theme/*.js" -# Tailwind config only -/workflow:ui-design:import-from-code --js "tailwind.config.js" +# Tailwind config only (output to current directory) +/workflow:ui-design:import-from-code --source-path ./ --js "tailwind.config.js" # CSS framework import -/workflow:ui-design:import-from-code --css "styles/**/*.scss" --html "components/**/*.html" +/workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system --css "styles/**/*.scss" --html "components/**/*.html" # Universal style files -/workflow:ui-design:import-from-code --style-files "**/theme.*" +/workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system --style-files "**/theme.*" ``` --- @@ -74,11 +75,12 @@ Extract design system tokens from source code files (CSS/SCSS/JS/TS/HTML) using ```bash # 1. Initialize directories -base_path="${base_path:-.}" -intermediates_dir="${base_path}/.intermediates/import-analysis" +source_path="${source_path:-.}" +output_path="${output_path:-.}" +intermediates_dir="${output_path}/.intermediates/import-analysis" mkdir -p "$intermediates_dir" -echo "[Phase 0] File Discovery Started" +echo "[Phase 0] File Discovery Started (source: $source_path, output: $output_path)" ``` @@ -95,7 +97,7 @@ echo "[Phase 0] File Discovery Started" ```bash # 2. Discover files by type -cd "$base_path" || exit 1 +cd "$source_path" || exit 1 # CSS files if [ -n "$css" ]; then @@ -181,7 +183,7 @@ Task(ui-design-agent): ` [STYLE_TOKENS_EXTRACTION] Extract visual design tokens (colors, typography, spacing, shadows, borders) from ALL file types - MODE: style-extraction | BASE_PATH: ${base_path} + MODE: style-extraction | SOURCE_PATH: ${source_path} | OUTPUT_PATH: ${output_path} ## Input Files (Can reference ANY file type) @@ -208,7 +210,7 @@ Task(ui-design-agent): ` ## Output Requirements - Generate 2 files in ${base_path}/style-extraction/style-1/: + Generate 2 files in ${output_path}/style-extraction/style-1/: 1. design-tokens.json (production-ready design tokens) 2. style-guide.md (design philosophy and usage guide) @@ -357,13 +359,13 @@ Task(ui-design-agent): ` ## Critical Requirements - ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML) - not restricted to CSS only - - ✅ Use Read() tool for each file you want to analyze + - ✅ Use Read() tool for each file you want to analyze (files are in SOURCE_PATH: ${source_path}) - ✅ Cross-reference between file types for better extraction - ✅ Extract all visual token types systematically - - ✅ Create style-extraction/style-1/ directory first: Bash(mkdir -p "${base_path}/style-extraction/style-1") + - ✅ Create style-extraction/style-1/ directory first: Bash(mkdir -p "${output_path}/style-extraction/style-1") - ✅ Use Write() to save both files: - - ${base_path}/style-extraction/style-1/design-tokens.json - - ${base_path}/style-extraction/style-1/style-guide.md + - ${output_path}/style-extraction/style-1/design-tokens.json + - ${output_path}/style-extraction/style-1/style-guide.md - ✅ Include _metadata.completeness field to track missing content - ❌ NO external research or MCP calls ` @@ -378,7 +380,7 @@ Task(ui-design-agent): ` [ANIMATION_TOKENS_EXTRACTION] Extract animation/transition tokens from ALL file types - MODE: animation-extraction | BASE_PATH: ${base_path} + MODE: animation-extraction | SOURCE_PATH: ${source_path} | OUTPUT_PATH: ${output_path} ## Input Files (Can reference ANY file type) @@ -405,7 +407,7 @@ Task(ui-design-agent): ` ## Output Requirements - Generate 2 files in ${base_path}/animation-extraction/: + Generate 2 files in ${output_path}/animation-extraction/: 1. animation-tokens.json (production-ready animation tokens) 2. animation-guide.md (animation usage guide) @@ -530,13 +532,13 @@ Task(ui-design-agent): ` ## Critical Requirements - ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML) - - ✅ Use Read() tool for each file you want to analyze + - ✅ Use Read() tool for each file you want to analyze (files are in SOURCE_PATH: ${source_path}) - ✅ Detect animation framework if used - ✅ Extract all animation-related tokens - - ✅ Create animation-extraction/ directory first: Bash(mkdir -p "${base_path}/animation-extraction") + - ✅ Create animation-extraction/ directory first: Bash(mkdir -p "${output_path}/animation-extraction") - ✅ Use Write() to save both files: - - ${base_path}/animation-extraction/animation-tokens.json - - ${base_path}/animation-extraction/animation-guide.md + - ${output_path}/animation-extraction/animation-tokens.json + - ${output_path}/animation-extraction/animation-guide.md - ✅ Include _metadata.completeness field to track missing content - ❌ NO external research or MCP calls ` @@ -551,7 +553,7 @@ Task(ui-design-agent): ` [LAYOUT_PATTERNS_EXTRACTION] Extract layout patterns and component structures from ALL file types - MODE: layout-extraction | BASE_PATH: ${base_path} + MODE: layout-extraction | SOURCE_PATH: ${source_path} | OUTPUT_PATH: ${output_path} ## Input Files (Can reference ANY file type) @@ -578,7 +580,7 @@ Task(ui-design-agent): ` ## Output Requirements - Generate 1 file: ${base_path}/layout-extraction/layout-templates.json + Generate 1 file: ${output_path}/layout-extraction/layout-templates.json ### layout-templates.json Structure: { @@ -675,11 +677,11 @@ Task(ui-design-agent): ` ## Critical Requirements - ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML) - - ✅ Use Read() tool for each file you want to analyze + - ✅ Use Read() tool for each file you want to analyze (files are in SOURCE_PATH: ${source_path}) - ✅ Identify naming conventions and layout systems - ✅ Extract component patterns with variants and states - - ✅ Create layout-extraction/ directory first: Bash(mkdir -p "${base_path}/layout-extraction") - - ✅ Use Write() to save: ${base_path}/layout-extraction/layout-templates.json + - ✅ Create layout-extraction/ directory first: Bash(mkdir -p "${output_path}/layout-extraction") + - ✅ Use Write() to save: ${output_path}/layout-extraction/layout-templates.json - ✅ Include extraction_metadata.completeness field to track missing content - ❌ NO external research or MCP calls ` @@ -710,11 +712,11 @@ echo "[Phase 1] Parallel agent analysis complete" ### Generated Files -**Location**: `${base_path}/` +**Location**: `${output_path}/` **Directory Structure**: ``` -${base_path}/ +${output_path}/ ├── style-extraction/ │ └── style-1/ │ ├── design-tokens.json # Production-ready design tokens @@ -769,7 +771,7 @@ ${base_path}/ | Error | Cause | Resolution | |-------|-------|------------| -| No files discovered | Glob patterns too restrictive or wrong base-path | Check glob patterns and base-path, verify file locations | +| No files discovered | Glob patterns too restrictive or wrong source-path | Check glob patterns and source-path, verify file locations | | Agent reports "failed" status | No tokens found in any file | Review file content, check if files contain design tokens | | Empty completeness reports | Files exist but contain no extractable tokens | Manually verify token definitions in source files | | Missing file type | Specific file type not discovered | Use explicit glob flags (--css, --js, --html, --scss) | @@ -779,7 +781,8 @@ ${base_path}/ ## Best Practices 1. **Use auto-discovery for full projects**: Omit glob flags to discover all files automatically -2. **Target specific directories for speed**: Use `--base-path` + specific globs for focused analysis -3. **Cross-reference agent reports**: Compare all three completeness reports to identify gaps -4. **Review missing content**: Check `missing` field in reports for actionable improvements -5. **Verify file discovery**: Check `.intermediates/import-analysis/*-files.txt` if agents report no data +2. **Target specific directories for speed**: Use `--source-path` to target source code and `--output-path` for extracted tokens, combined with specific globs for focused analysis +3. **Separate source and output**: Always use distinct `--source-path` (where source code lives) and `--output-path` (where design tokens are generated) to avoid polluting source code directory +4. **Cross-reference agent reports**: Compare all three completeness reports to identify gaps +5. **Review missing content**: Check `missing` field in reports for actionable improvements +6. **Verify file discovery**: Check `${output_path}/.intermediates/import-analysis/*-files.txt` if agents report no data diff --git a/.claude/commands/workflow/ui-design/layout-extract.md b/.claude/commands/workflow/ui-design/layout-extract.md index 981cfd1e..77ed6760 100644 --- a/.claude/commands/workflow/ui-design/layout-extract.md +++ b/.claude/commands/workflow/ui-design/layout-extract.md @@ -1,7 +1,7 @@ --- name: layout-extract description: Extract structural layout information from reference images, URLs, or text prompts using Claude analysis -argument-hint: [--base-path ] [--session ] [--images ""] [--urls ""] [--prompt ""] [--targets ""] [--mode ] [--variants ] [--device-type ] +argument-hint: [--base-path ] [--session ] [--images ""] [--urls ""] [--prompt ""] [--targets ""] [--variants ] [--device-type ] allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), Bash(*), Task(ui-design-agent), mcp__exa__web_search_exa(*) --- @@ -14,10 +14,8 @@ Extract structural layout information from reference images, URLs, or text promp **Strategy**: AI-Driven Structural Analysis - **Agent-Powered**: Uses `ui-design-agent` for deep structural analysis -- **Dual-Mode**: - - `imitate`: High-fidelity replication of single layout structure - - `explore`: Multiple structurally distinct layout variations -- **Single Output**: `layout-templates.json` with DOM structure, component hierarchy, and CSS layout rules +- **Behavior**: Generate N layout concepts → User multi-select → Generate selected templates +- **Output**: `layout-templates.json` with DOM structure, component hierarchy, and CSS layout rules - **Device-Aware**: Optimized for specific device types (desktop, mobile, tablet, responsive) - **Token-Based**: CSS uses `var()` placeholders for spacing and breakpoints @@ -45,15 +43,10 @@ ELSE: has_urls = false url_list = [] -# Determine extraction mode -extraction_mode = --mode OR "imitate" # "imitate" or "explore" - -# Set variants count based on mode -IF extraction_mode == "imitate": - variants_count = 1 # Force single variant (ignore --variants) -ELSE IF extraction_mode == "explore": - variants_count = --variants OR 3 # Default to 3 - VALIDATE: 1 <= variants_count <= 5 +# Set variants count (default: 3, range: 1-5) +# Behavior: Generate N layout concepts per target → User multi-select → Generate selected templates +variants_count = --variants OR 3 +VALIDATE: 1 <= variants_count <= 5 # Resolve targets # Priority: --targets → url_list targets → prompt analysis → default ["page"] @@ -62,6 +55,9 @@ IF --targets: ELSE IF has_urls: targets = [url_info.target for url_info in url_list] ELSE IF --prompt: + # Extract targets from prompt using pattern matching + # Looks for keywords: "page names", target descriptors (login, dashboard, etc.) + # Returns lowercase, hyphenated strings (e.g., ["login", "dashboard"]) targets = extract_from_prompt(--prompt) ELSE: targets = ["page"] @@ -190,36 +186,17 @@ IF result.exploration?.triggered: IF session_has_inputs: SKIP Step 2 file reading # 2. Check if output already exists -bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists") +bash(find {base_path}/layout-extraction -name "layout-*.json" -print -quit | grep -q . && echo "exists") IF exists: SKIP to completion ``` --- -**Phase 0 Output**: `input_mode`, `base_path`, `extraction_mode`, `variants_count`, `targets[]`, `device_type`, loaded inputs +**Phase 0 Output**: `input_mode`, `base_path`, `variants_count`, `targets[]`, `device_type`, loaded inputs -## Phase 1: Layout Concept Generation (Explore Mode Only) +## Phase 1: Layout Concept Generation -### Step 1: Check Extraction Mode -```bash -# extraction_mode == "imitate" → skip this phase -# extraction_mode == "explore" → execute this phase -``` - -**If imitate mode**: Skip to Phase 2 - -### Step 2: Gather Layout Inspiration (Explore Mode) -```bash -bash(mkdir -p {base_path}/.intermediates/layout-analysis/inspirations) - -# For each target: Research via MCP -# mcp__exa__web_search_exa(query="{target} layout patterns {device_type}", numResults=5) - -# Write inspiration file -Write({base_path}/.intermediates/layout-analysis/inspirations/{target}-layout-ideas.txt, inspiration_content) -``` - -### Step 3: Generate Layout Concept Options (Agent Task 1) +### Step 1: Generate Layout Concept Options (Agent Task 1) **Executor**: `Task(ui-design-agent)` Launch agent to generate `variants_count` layout concept options for each target: @@ -235,7 +212,6 @@ Task(ui-design-agent): ` ## Input Analysis - Targets: {targets.join(", ")} - Device type: {device_type} - - Layout inspiration: Read inspirations from {base_path}/.intermediates/layout-analysis/inspirations/ - Visual references: {loaded_images if available} ${dom_structure_available ? "- DOM Structure: Read from .intermediates/layout-analysis/dom-structure-*.json" : ""} @@ -272,7 +248,7 @@ Task(ui-design-agent): ` ` ``` -### Step 4: Verify Options File Created +### Step 2: Verify Options File Created ```bash bash(test -f {base_path}/.intermediates/layout-analysis/analysis-options.json && echo "created") @@ -333,13 +309,13 @@ Please select your preferred concept for this target. ### Step 3: Capture User Selection (Per Target) ```javascript -// Use AskUserQuestion tool for each target +// Use AskUserQuestion tool for each target (multi-select enabled) FOR each target: AskUserQuestion({ questions: [{ - question: "Which layout concept do you prefer for '{target}'?", + question: "Which layout concept(s) do you prefer for '{target}'?", header: "Layout for " + target, - multiSelect: false, + multiSelect: true, // Multi-selection enabled (default behavior) options: [ {FOR each concept in layout_concepts[target]: label: "Concept {concept.index}: {concept.concept_name}", @@ -349,39 +325,47 @@ FOR each target: }] }) - // Parse user response - selected_option_text = user_answer + // Parse user response (array of selections) + selected_options = user_answer // Check for user cancellation - IF selected_option_text == null OR selected_option_text == "": + IF selected_options == null OR selected_options.length == 0: REPORT: "⚠️ User canceled selection. Workflow terminated." EXIT workflow - // Extract concept index from response format "Concept N: Name" - match = selected_option_text.match(/Concept (\d+):/) - IF match: - selected_index = parseInt(match[1]) - ELSE: - ERROR: "Invalid selection format. Expected 'Concept N: ...' format" - EXIT workflow + // Extract concept indices from array + selected_indices = [] + FOR each selected_option_text IN selected_options: + match = selected_option_text.match(/Concept (\d+):/) + IF match: + selected_indices.push(parseInt(match[1])) + ELSE: + ERROR: "Invalid selection format. Expected 'Concept N: ...' format" + EXIT workflow - // Store selection for this target + // Store selections for this target (array of indices) selections[target] = { - selected_index: selected_index, - concept_name: layout_concepts[target][selected_index-1].concept_name + selected_indices: selected_indices, // Array of selected indices + concept_names: selected_indices.map(i => layout_concepts[target][i-1].concept_name) } + + REPORT: "✅ Selected {selected_indices.length} layout(s) for {target}" ``` ### Step 4: Write User Selection File ```bash +# Calculate total selections across all targets +total_selections = sum([len(selections[t].selected_indices) for t in targets]) + # Create user selection JSON selection_data = { "metadata": { "selected_at": "{current_timestamp}", - "selection_type": "per_target", - "session_id": "{session_id}" + "selection_type": "per_target_multi", + "session_id": "{session_id}", + "total_selections": total_selections }, - "selections": selections // {target: {selected_index, concept_name}} + "selections": selections // {target: {selected_indices: [...], concept_names: [...]}} } # Write to file @@ -393,149 +377,155 @@ bash(test -f {base_path}/.intermediates/layout-analysis/user-selection.json && e ### Step 5: Confirmation Message ``` -✅ Selections recorded! +✅ Selections recorded! Total: {total_selections} layout(s) {FOR each target, selection in selections: - • {target}: Concept {selection.selected_index} - {selection.concept_name} + • {target}: {selection.selected_indices.length} layout(s) selected + {FOR each index IN selection.selected_indices: + - Concept {index}: {layout_concepts[target][index-1].concept_name} + } } -Proceeding to generate detailed layout templates based on your selections... +Proceeding to generate {total_selections} detailed layout template(s)... ``` -**Output**: `user-selection.json` with user's choices for all targets +**Output**: `user-selection.json` with user's multi-selections for all targets ## Phase 2: Layout Template Generation (Agent Task 2) -**Executor**: `Task(ui-design-agent)` for selected concept(s) +**Executor**: `Task(ui-design-agent)` × `Total_Selected_Templates` in **parallel** -### Step 1: Load User Selection (Explore Mode) +### Step 1: Load User Selections and Build Task List ```bash -# For explore mode, read user selection -IF extraction_mode == "explore": - selection = Read({base_path}/.intermediates/layout-analysis/user-selection.json) - selections_per_target = selection.selections +# Read user selections +selection = Read({base_path}/.intermediates/layout-analysis/user-selection.json) +selections_per_target = selection.selections - # Also read the selected concept details from options - options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json) - layout_concepts = options.layout_concepts +# Read concept details +options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json) +layout_concepts = options.layout_concepts - # Build selected concepts map - selected_concepts = {} - FOR each target in targets: - selected_index = selections_per_target[target].selected_index - selected_concepts[target] = layout_concepts[target][selected_index-1] # 0-indexed -ELSE: - # Imitate mode - no selection needed - selected_concepts = null +# Build task list for all selected concepts across all targets +task_list = [] +FOR each target in targets: + selected_indices = selections_per_target[target].selected_indices # Array + concept_names = selections_per_target[target].concept_names # Array + + FOR i in range(len(selected_indices)): + idx = selected_indices[i] + concept = layout_concepts[target][idx - 1] # 0-indexed array + variant_id = i + 1 # 1-based variant numbering + + task_list.push({ + target: target, + variant_id: variant_id, + concept: concept, + output_file: "{base_path}/layout-extraction/layout-{target}-{variant_id}.json" + }) + +total_tasks = task_list.length +REPORT: "Generating {total_tasks} layout templates across {targets.length} targets" ``` -### Step 2: Launch Agent Task -Generate layout templates for selected concepts: +### Step 2: Launch Parallel Agent Tasks +Generate layout templates for ALL selected concepts in parallel: ```javascript -Task(ui-design-agent): ` - [LAYOUT_TEMPLATE_GENERATION_TASK] - Generate detailed layout templates based on user-selected concepts. - Focus ONLY on structure and layout. DO NOT concern with visual style (colors, fonts, etc.). +FOR each task in task_list: + Task(ui-design-agent): ` + [LAYOUT_TEMPLATE_GENERATION_TASK #{task.variant_id} for {task.target}] + Generate detailed layout template based on user-selected concept. + Focus ONLY on structure and layout. DO NOT concern with visual style (colors, fonts, etc.). - SESSION: {session_id} | MODE: {extraction_mode} | BASE_PATH: {base_path} - DEVICE_TYPE: {device_type} + SESSION: {session_id} | BASE_PATH: {base_path} + TARGET: {task.target} | VARIANT: {task.variant_id} + DEVICE_TYPE: {device_type} - ${extraction_mode == "explore" ? ` - USER SELECTIONS: - ${targets.map(target => ` - Target: ${target} - - Selected Concept: ${selected_concepts[target].concept_name} - - Philosophy: ${selected_concepts[target].design_philosophy} - - Pattern: ${selected_concepts[target].layout_pattern} - - Key Components: ${selected_concepts[target].key_components.join(", ")} - - Structural Features: ${selected_concepts[target].structural_features.join(", ")} - `).join("\n")} - ` : ` - MODE: Imitate - High-fidelity replication of reference layout structure - TARGETS: ${targets.join(", ")} - `} + USER SELECTION: + - Selected Concept: {task.concept.concept_name} + - Philosophy: {task.concept.design_philosophy} + - Pattern: {task.concept.layout_pattern} + - Key Components: {task.concept.key_components.join(", ")} + - Structural Features: {task.concept.structural_features.join(", ")} - ## Input Analysis - - Targets: {targets.join(", ")} - - Device type: {device_type} - - Visual references: {loaded_images if available} - ${dom_structure_available ? "- DOM Structure Data: Read from .intermediates/layout-analysis/dom-structure-*.json - USE THIS for accurate layout properties" : ""} + ## Input Analysis + - Target: {task.target} + - Device type: {device_type} + - Visual references: {loaded_images if available} + ${dom_structure_available ? "- DOM Structure Data: Read from .intermediates/layout-analysis/dom-structure-{task.target}.json - USE THIS for accurate layout properties" : ""} - ## Generation Rules - ${extraction_mode == "explore" ? ` - - **Explore Mode**: Develop each user-selected layout concept into a detailed template - - Use the selected concept's key_components as foundation - - Apply the selected layout_pattern (grid-3col, flex-row, etc.) - - Honor the structural_features defined in the concept - - Expand the concept with complete DOM structure and CSS layout rules - ` : ` - - **Imitate Mode**: High-fidelity replication of reference layout structure - ${dom_structure_available ? "- Use DOM structure data as ground truth" : "- Use visual inference"} - `} - ${dom_structure_available ? ` - - IMPORTANT: You have access to real DOM structure data with accurate flex/grid properties - - Use DOM data as primary source for layout properties - - Extract real flex/grid configurations (display, flexDirection, justifyContent, alignItems, gap) - - Use actual element bounds for responsive breakpoint decisions - - Preserve identified patterns from DOM structure - ` : ""} + ## Generation Rules + - Develop the user-selected layout concept into a detailed template + - Use the selected concept's key_components as foundation + - Apply the selected layout_pattern (grid-3col, flex-row, etc.) + - Honor the structural_features defined in the concept + - Expand the concept with complete DOM structure and CSS layout rules + ${dom_structure_available ? ` + - IMPORTANT: You have access to real DOM structure data with accurate flex/grid properties + - Use DOM data as primary source for layout properties + - Extract real flex/grid configurations (display, flexDirection, justifyContent, alignItems, gap) + - Use actual element bounds for responsive breakpoint decisions + - Preserve identified patterns from DOM structure + ` : ""} - ## Generate for EACH Target - For target in {targets}: - ${extraction_mode == "explore" ? "Based on user-selected concept:" : "Based on reference:"} + ## Template Generation - 1. **DOM Structure**: - - Semantic HTML5 tags:
,