diff --git a/skills/always-use-superpowers/SKILL.md b/skills/always-use-superpowers/SKILL.md index 6263ab46..0697fc89 100644 --- a/skills/always-use-superpowers/SKILL.md +++ b/skills/always-use-superpowers/SKILL.md @@ -56,7 +56,14 @@ You MUST: - Use before: Any design work, HTML/CSS, component creation, layouts - Priority: HIGH for any UI/UX work -#### 5. codebase-indexer (ALWAYS ACTIVE) +#### 5. design-pattern-learner +**When to use:** Studying or implementing designs from external sources +- Use before: Learning from gists, repositories, or external websites +- Triggers on: "study design from", "learn from", "implement this design", "copy style from" +- Priority: HIGH for external design learning +- Benefit: Fetches, analyzes, and implements patterns from any design source + +#### 6. codebase-indexer (ALWAYS ACTIVE) **When to use:** EVERY TASK involving code navigation, file searches, codebase understanding - **ALWAYS RUN THIS FIRST** before any code-related task - Use for: Finding files, understanding code structure, semantic search, 40-60% token reduction @@ -79,6 +86,9 @@ User sends message Check: Is this code-related work? ↓ YES → Invoke codebase-indexer (ALWAYS) ↓ NO +Check: Is this studying/learning external design? + ↓ YES → Invoke design-pattern-learner + ↓ NO Check: Is this UI/UX work? ↓ YES → Invoke ui-ux-pro-max ↓ NO diff --git a/skills/design-pattern-learner/README.md b/skills/design-pattern-learner/README.md new file mode 100644 index 00000000..b451825e --- /dev/null +++ b/skills/design-pattern-learner/README.md @@ -0,0 +1,35 @@ +# Design Pattern Learner Skill + +**Auto-triggers when user wants to study/learn from external design sources** + +## Quick Start + +```bash +# Analyze a design source +python3 scripts/analyze.py "https://gist.github.com/user/id" + +# Generate implementation +python3 scripts/generate.py --source ~/.claude/skills/design-pattern-learner/data/patterns/[file] --framework tailwind +``` + +## What It Does + +1. **Fetches** designs from gists, repos, or webpages +2. **Analyzes** design tokens (colors, typography, spacing, effects) +3. **Extracts** components (buttons, cards, modals, etc.) +4. **Generates** implementation code (Tailwind, React, Vue) + +## Auto-Trigger Patterns + +- "study design from [URL]" +- "learn from [source]" +- "implement this design" +- "copy style from" +- "replicate this pattern" + +## Integration + +Works alongside: +- `ui-ux-pro-max` - Design guidance +- `codebase-indexer` - Find files +- `always-use-superpowers` - Auto-dispatch diff --git a/skills/design-pattern-learner/scripts/analyze.py b/skills/design-pattern-learner/scripts/analyze.py new file mode 100755 index 00000000..bafb9aa7 --- /dev/null +++ b/skills/design-pattern-learner/scripts/analyze.py @@ -0,0 +1,453 @@ +#!/usr/bin/env python3 +""" +Design Pattern Analyzer +Fetches and analyzes design patterns from external sources +""" + +import sys +import json +import re +import os +from urllib.parse import urlparse +from datetime import datetime +import subprocess + +class DesignPatternAnalyzer: + def __init__(self, source_url): + self.source_url = source_url + self.patterns = { + "source": source_url, + "timestamp": datetime.now().isoformat(), + "design_tokens": {}, + "components": [], + "layouts": [], + "animations": [] + } + + def fetch_source(self): + """Fetch content from URL/gist/repo""" + print(f"📥 Fetching source: {self.source_url}") + + # Detect source type + if "gist.github.com" in self.source_url: + return self._fetch_gist() + elif "github.com" in self.source_url: + return self._fetch_github_repo() + else: + return self._fetch_webpage() + + def _fetch_gist(self): + """Fetch gist content using git""" + print("🔍 Detected: GitHub Gist") + + # Extract gist ID + gist_match = re.search(r'gist\.github\.com/[^/]+/([a-f0-9]+)', self.source_url) + if not gist_match: + gist_match = re.search(r'gist\.github\.com/([a-f0-9]+)', self.source_url) + + if gist_match: + gist_id = gist_match.group(1) + gist_url = f"https://gist.github.com/{gist_id}" + + # Use curl to fetch + result = subprocess.run( + ['curl', '-s', gist_url], + capture_output=True, + text=True + ) + + if result.returncode == 0: + return self._parse_gist_html(result.stdout) + else: + print(f"❌ Failed to fetch gist: {result.stderr}") + return None + else: + print("❌ Could not extract gist ID") + return None + + def _fetch_github_repo(self): + """Fetch GitHub repository""" + print("🔍 Detected: GitHub Repository") + print("⚠️ Repo analysis requires cloning - will analyze README and structure") + + # For now, analyze the main page + result = subprocess.run( + ['curl', '-s', self.source_url], + capture_output=True, + text=True + ) + + if result.returncode == 0: + return self._parse_github_page(result.stdout) + else: + print(f"❌ Failed to fetch repo: {result.stderr}") + return None + + def _fetch_webpage(self): + """Fetch regular webpage""" + print("🔍 Detected: Webpage") + + result = subprocess.run( + ['curl', '-s', '-L', self.source_url], + capture_output=True, + text=True + ) + + if result.returncode == 0: + return result.stdout + else: + print(f"❌ Failed to fetch webpage: {result.stderr}") + return None + + def _parse_gist_html(self, html): + """Parse gist HTML to extract code""" + print("📄 Parsing gist content...") + + # Look for file content in gist HTML + # Extract from
or similar + file_pattern = r'
]*>(.*?)
' + files = re.findall(file_pattern, html, re.DOTALL) + + if files: + # Clean up HTML entities and tags + content = [] + for file_html in files: + # Remove HTML tags but keep code + clean_code = re.sub(r'<[^>]+>', '\n', file_html) + clean_code = re.sub(r'<', '<', clean_code) + clean_code = re.sub(r'>', '>', clean_code) + clean_code = re.sub(r'&', '&', clean_code) + clean_code = re.sub(r'\n\s*\n', '\n', clean_code) + content.append(clean_code.strip()) + + return '\n\n'.join(content) + else: + print("⚠️ Could not extract gist files") + return html + + def _parse_github_page(self, html): + """Parse GitHub repo page""" + print("📄 Parsing repository page...") + return html + + def analyze_design_tokens(self, content): + """Extract design tokens from content""" + print("\n🎨 Extracting Design Tokens...") + + tokens = {} + + # Colors + colors = self._extract_colors(content) + if colors: + tokens['colors'] = colors + print(f" ✓ Found {len(colors)} color patterns") + + # Typography + typography = self._extract_typography(content) + if typography: + tokens['typography'] = typography + print(f" ✓ Found {len(typography.get('fonts', []))} font patterns") + + # Spacing + spacing = self._extract_spacing(content) + if spacing: + tokens['spacing'] = spacing + print(f" ✓ Found spacing patterns") + + # Effects + effects = self._extract_effects(content) + if effects: + tokens['effects'] = effects + print(f" ✓ Found {len(effects.get('shadows', []))} shadow patterns") + + self.patterns['design_tokens'] = tokens + return tokens + + def _extract_colors(self, content): + """Extract color patterns""" + colors = {} + + # Hex colors + hex_colors = re.findall(r'#[0-9a-fA-F]{3,6}', content) + if hex_colors: + colors['hex'] = list(set(hex_colors))[:20] # Limit to 20 unique + + # Tailwind color classes + tailwind_colors = re.findall(r'\b(bg|text|border)-([a-z]+)-(\d+)\b', content) + if tailwind_colors: + colors['tailwind'] = [ + f"{prefix}-{color}-{shade}" + for prefix, color, shade in tailwind_colors + ][:20] + + # CSS color names + css_colors = re.findall(r'\b(black|white|gray|red|blue|green|yellow|purple|pink|indigo)\b', content, re.I) + if css_colors: + colors['css'] = list(set(css_colors)) + + return colors if colors else None + + def _extract_typography(self, content): + """Extract typography patterns""" + typo = {} + + # Font families + fonts = re.findall(r'font-family:\s*([^;]+)', content, re.I) + if fonts: + typo['fonts'] = list(set(fonts)) + + # Font sizes + sizes = re.findall(r'(text-|font-)?size:\s*([^;]+)', content, re.I) + if sizes: + typo['sizes'] = list(set([s[1] for s in sizes])) + + # Tailwind text classes + tailwind_text = re.findall(r'\b(text|font)-(xl|lg|md|sm|xs|\d)\b', content) + if tailwind_text: + typo['tailwind'] = [f"{prefix}-{size}" for prefix, size in tailwind_text] + + return typo if typo else None + + def _extract_spacing(self, content): + """Extract spacing patterns""" + spacing = {} + + # Tailwind spacing + tailwind_spacing = re.findall(r'\b(p|m|px|py|pt|pb|pl|pr)-(\\d+)\b', content) + if tailwind_spacing: + spacing['tailwind'] = list(set([f"{prefix}-{size}" for prefix, size in tailwind_spacing])) + + # CSS spacing + css_spacing = re.findall(r'(padding|margin):\s*([^;]+)', content, re.I) + if css_spacing: + spacing['css'] = list(set([f"{prop}: {val}" for prop, val in css_spacing])) + + return spacing if spacing else None + + def _extract_effects(self, content): + """Extract visual effects""" + effects = {} + + # Shadows + shadows = re.findall(r'box-shadow:\s*([^;]+)', content, re.I) + if shadows: + effects['shadows'] = list(set(shadows)) + + # Tailwind shadows + tailwind_shadows = re.findall(r'\bshadow-(xl|lg|md|sm|none)\b', content) + if tailwind_shadows: + effects['tailwind_shadows'] = [f"shadow-{s}" for s in tailwind_shadows] + + # Border radius + radius = re.findall(r'border-radius:\s*([^;]+)', content, re.I) + if radius: + effects['radius'] = list(set(radius)) + + return effects if effects else None + + def analyze_components(self, content): + """Extract UI components""" + print("\n🧩 Identifying Components...") + + components = [] + + # Look for common component patterns + component_patterns = { + 'button': r']*>.*?|class="[^"]*button[^"]*"', + 'card': r'class="[^"]*card[^"]*"', + 'modal': r'class="[^"]*modal[^"]*"', + 'nav': r']*>.*?|class="[^"]*nav[^"]*"', + 'form': r']*>.*?|class="[^"]*form[^"]*"', + 'input': r']*/?>|class="[^"]*input[^"]*"', + 'hero': r'class="[^"]*hero[^"]*"', + 'footer': r']*>.*?', + 'header': r']*>.*?', + } + + for comp_name, pattern in component_patterns.items(): + matches = re.findall(pattern, content, re.DOTALL | re.IGNORECASE) + if matches: + components.append({ + 'type': comp_name, + 'count': len(matches), + 'examples': matches[:3] # First 3 examples + }) + print(f" ✓ Found {len(matches)} {comp_name} component(s)") + + self.patterns['components'] = components + return components + + def analyze_layouts(self, content): + """Extract layout patterns""" + print("\n📐 Analyzing Layouts...") + + layouts = [] + + # Grid layouts + grids = re.findall(r'grid-cols-\\d+', content) + if grids: + layouts.append({ + 'type': 'grid', + 'variants': list(set(grids)) + }) + print(f" ✓ Found grid layouts: {list(set(grids))}") + + # Flexbox + flex_patterns = re.findall(r'flex-(row|col|wrap|nowrap)', content) + if flex_patterns: + layouts.append({ + 'type': 'flexbox', + 'patterns': list(set(flex_patterns)) + }) + print(f" ✓ Found flexbox patterns: {list(set(flex_patterns))}") + + # Containers + containers = re.findall(r'class="[^"]*container[^"]*"', content) + if containers: + layouts.append({ + 'type': 'container', + 'count': len(containers) + }) + print(f" ✓ Found {len(containers)} container(s)") + + self.patterns['layouts'] = layouts + return layouts + + def analyze_animations(self, content): + """Extract animation patterns""" + print("\n✨ Analyzing Animations...") + + animations = [] + + # Transitions + transitions = re.findall(r'transition(?:-[^:]*)?:\\s*([^;]+)', content, re.I) + if transitions: + animations.append({ + 'type': 'transition', + 'patterns': list(set(transitions))[:10] + }) + print(f" ✓ Found transitions: {len(set(transitions))}") + + # Transforms + transforms = re.findall(r'transform:\\s*([^;]+)', content, re.I) + if transforms: + animations.append({ + 'type': 'transform', + 'patterns': list(set(transforms)) + }) + print(f" ✓ Found transforms: {len(set(transforms))}") + + # Keyframes + keyframes = re.findall(r'@keyframes\\s+(\\w+)', content) + if keyframes: + animations.append({ + 'type': 'keyframe', + 'names': list(set(keyframes)) + }) + print(f" ✓ Found keyframes: {list(set(keyframes))}") + + self.patterns['animations'] = animations + return animations + + def save_patterns(self): + """Save extracted patterns to file""" + # Create data directory if needed + data_dir = os.path.expanduser('~/.claude/skills/design-pattern-learner/data/patterns') + os.makedirs(data_dir, exist_ok=True) + + # Generate filename from URL + safe_name = re.sub(r'[^a-zA-Z0-9]', '_', self.source_url)[:50] + timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') + filename = f"{safe_name}_{timestamp}.json" + filepath = os.path.join(data_dir, filename) + + # Save patterns + with open(filepath, 'w') as f: + json.dump(self.patterns, f, indent=2) + + print(f"\n💾 Patterns saved to: {filepath}") + + # Also save to learning history + history_file = os.path.expanduser('~/.claude/skills/design-pattern-learner/learning-history.jsonl') + with open(history_file, 'a') as f: + f.write(json.dumps({ + 'timestamp': datetime.now().isoformat(), + 'source': self.source_url, + 'file': filename, + 'patterns_count': len(self.patterns['components']), + 'success': True + }) + '\n') + + return filepath + + def generate_summary(self): + """Generate human-readable summary""" + print("\n" + "="*60) + print("📊 DESIGN PATTERN ANALYSIS SUMMARY") + print("="*60) + + print(f"\n📍 Source: {self.source_url}") + print(f"🕐 Analyzed: {self.patterns['timestamp']}") + + # Design tokens + if self.patterns['design_tokens']: + print("\n🎨 Design Tokens:") + for category, values in self.patterns['design_tokens'].items(): + print(f" • {category}: {len(values)} patterns") + + # Components + if self.patterns['components']: + print(f"\n🧩 Components Found: {len(self.patterns['components'])}") + for comp in self.patterns['components']: + print(f" • {comp['type']}: {comp['count']} instance(s)") + + # Layouts + if self.patterns['layouts']: + print(f"\n📐 Layout Patterns: {len(self.patterns['layouts'])}") + for layout in self.patterns['layouts']: + print(f" • {layout['type']}") + + # Animations + if self.patterns['animations']: + print(f"\n✨ Animations: {len(self.patterns['animations'])}") + for anim in self.patterns['animations']: + print(f" • {anim['type']}") + + print("\n" + "="*60) + print("✅ Analysis Complete!") + print("="*60) + +def main(): + if len(sys.argv) < 2: + print("Usage: python3 analyze.py ") + print("Example: python3 analyze.py https://gist.github.com/user/id") + sys.exit(1) + + url = sys.argv[1] + + analyzer = DesignPatternAnalyzer(url) + + # Fetch content + content = analyzer.fetch_source() + if not content: + print("❌ Failed to fetch content") + sys.exit(1) + + # Analyze patterns + analyzer.analyze_design_tokens(content) + analyzer.analyze_components(content) + analyzer.analyze_layouts(content) + analyzer.analyze_animations(content) + + # Save results + filepath = analyzer.save_patterns() + + # Show summary + analyzer.generate_summary() + + print(f"\n💡 Next steps:") + print(f" • View patterns: cat {filepath}") + print(f" • Generate implementation: python3 generate.py --source {filepath}") + +if __name__ == '__main__': + main() diff --git a/skills/design-pattern-learner/scripts/generate.py b/skills/design-pattern-learner/scripts/generate.py new file mode 100755 index 00000000..e9ae6a7f --- /dev/null +++ b/skills/design-pattern-learner/scripts/generate.py @@ -0,0 +1,502 @@ +#!/usr/bin/env python3 +""" +Pattern Implementation Generator +Generates implementation code from analyzed patterns +""" + +import sys +import json +import os +from datetime import datetime + +class PatternGenerator: + def __init__(self, pattern_file, framework='tailwind'): + self.pattern_file = pattern_file + self.framework = framework + self.patterns = None + + def load_patterns(self): + """Load pattern JSON file""" + print(f"📖 Loading patterns from: {self.pattern_file}") + + try: + with open(self.pattern_file, 'r') as f: + self.patterns = json.load(f) + print(f"✅ Patterns loaded successfully") + return True + except Exception as e: + print(f"❌ Error loading patterns: {e}") + return False + + def generate_component_library(self): + """Generate component library from patterns""" + print(f"\n🧩 Generating Component Library for {self.framework}...") + + if not self.patterns.get('components'): + print("⚠️ No components found in patterns") + return {} + + library = {} + + for comp in self.patterns['components']: + comp_type = comp['type'] + examples = comp.get('examples', []) + + if not examples: + continue + + library[comp_type] = { + 'count': comp['count'], + 'implementations': [] + } + + for i, example in enumerate(examples[:2]): # Max 2 examples + impl = self._convert_to_framework(comp_type, example) + if impl: + library[comp_type]['implementations'].append(impl) + + print(f" ✓ Generated {comp_type} component") + + return library + + def _convert_to_framework(self, comp_type, html_snippet): + """Convert HTML snippet to target framework""" + + # Clean up the snippet + snippet = html_snippet.strip() + + if self.framework == 'tailwind': + return self._convert_tailwind(comp_type, snippet) + elif self.framework == 'react': + return self._convert_react(comp_type, snippet) + elif self.framework == 'vue': + return self._convert_vue(comp_type, snippet) + else: + return {'html': snippet} + + def _convert_tailwind(self, comp_type, snippet): + """Convert to Tailwind HTML""" + # Extract classes if present + import re + + classes = re.findall(r'class="([^"]*)"', snippet) + all_classes = ' '.join(classes) if classes else '' + + return { + 'framework': 'tailwind', + 'html': snippet, + 'classes': all_classes, + 'usage': f'' + } + + def _convert_react(self, comp_type, snippet): + """Convert to React component""" + import re + + # Extract classes + classes = re.findall(r'class="([^"]*)"', snippet) + + # Convert to JSX + jsx = snippet + # Replace class with className + jsx = re.sub(r'class=', 'className=', jsx) + # Close self-closing tags + jsx = re.sub(r']*)>', r'', jsx) + + component_name = ''.join([w.capitalize() for w in comp_type.split('_')]) + + return { + 'framework': 'react', + 'component_name': component_name, + 'jsx': jsx, + 'code': f'''export function {component_name}() {{ + return ( +{self._indent_jsx(jsx, 4)} + ); +}}''' + } + + def _convert_vue(self, comp_type, snippet): + """Convert to Vue component""" + component_name = ''.join([w.capitalize() for w in comp_type.split('_')]) + + return { + 'framework': 'vue', + 'component_name': component_name, + 'template': snippet, + 'code': f''' + +''' + } + + def _indent_jsx(self, code, spaces): + """Indent multi-line JSX/Vue code""" + lines = code.split('\n') + indent = ' ' * spaces + return '\n'.join([indent + line if line.strip() else line for line in lines]) + + def generate_design_system(self): + """Generate design system from tokens""" + print(f"\n🎨 Generating Design System...") + + if not self.patterns.get('design_tokens'): + print("⚠️ No design tokens found") + return {} + + tokens = self.patterns['design_tokens'] + design_system = {} + + # Colors + if 'colors' in tokens: + design_system['colors'] = self._generate_color_tokens(tokens['colors']) + + # Typography + if 'typography' in tokens: + design_system['typography'] = self._generate_typography_tokens(tokens['typography']) + + # Spacing + if 'spacing' in tokens: + design_system['spacing'] = self._generate_spacing_tokens(tokens['spacing']) + + # Effects + if 'effects' in tokens: + design_system['effects'] = self._generate_effect_tokens(tokens['effects']) + + return design_system + + def _generate_color_tokens(self, colors): + """Generate color tokens""" + tokens = {'tailwind': {}, 'hex': {}} + + if 'tailwind' in colors: + # Group by color name + for color_class in colors['tailwind']: + parts = color_class.split('-') + if len(parts) >= 3: + prop, color, shade = parts[0], parts[1], parts[2] + if color not in tokens['tailwind']: + tokens['tailwind'][color] = [] + tokens['tailwind'][color].append(shade) + + if 'hex' in colors: + tokens['hex'] = colors['hex'][:10] # Limit to 10 + + return tokens + + def _generate_typography_tokens(self, typography): + """Generate typography tokens""" + tokens = {} + + if 'fonts' in typography: + tokens['font_families'] = typography['fonts'] + + if 'sizes' in typography: + tokens['font_sizes'] = typography['sizes'] + + if 'tailwind' in typography: + tokens['tailwind_classes'] = typography['tailwind'] + + return tokens + + def _generate_spacing_tokens(self, spacing): + """Generate spacing tokens""" + tokens = {} + + if 'tailwind' in spacing: + # Extract unique spacing values + values = set() + for class_name in spacing['tailwind']: + parts = class_name.split('-') + if len(parts) >= 2: + values.add(parts[-1]) + tokens['tailwind_scale'] = list(values) + + if 'css' in spacing: + tokens['css_values'] = spacing['css'][:5] + + return tokens + + def _generate_effect_tokens(self, effects): + """Generate effect tokens""" + tokens = {} + + if 'shadows' in effects: + tokens['box_shadows'] = effects['shadows'][:5] + + if 'tailwind_shadows' in effects: + tokens['tailwind_shadows'] = effects['tailwind_shadows'] + + if 'radius' in effects: + tokens['border_radius'] = effects['radius'] + + return tokens + + def generate_implementation_guide(self): + """Generate implementation guide""" + print(f"\n📖 Generating Implementation Guide...") + + source = self.patterns.get('source', 'Unknown') + timestamp = self.patterns.get('timestamp', datetime.now().isoformat()) + + guide = f'''# Design Pattern Implementation Guide + +**Source:** {source} +**Analyzed:** {timestamp} +**Framework:** {self.framework} + +## Quick Start + +1. Review the design tokens below +2. Copy component code for your needs +3. Integrate into your project +4. Customize as needed + +--- + +## Design System + +### Colors +{self._format_colors()} + +### Typography +{self._format_typography()} + +### Spacing +{self._format_spacing()} + +### Effects +{self._format_effects()} + +--- + +## Components + +{self._format_components()} + +--- + +## Usage Examples + +### Applying Design Tokens + +```{self.framework} + +
+ Content here +
+``` + +### Using Components + +Copy any component from the Components section above and adapt to your needs. + +--- + +## Customization + +### Modify Colors +Update your Tailwind config or CSS variables to match the design tokens. + +### Adjust Spacing +Scale spacing values up or down based on your design system. + +### Add Effects +Apply the shadow and radius patterns to other components. + +--- + +## Attribution + +This implementation is based on design patterns from: {source} + +Please respect the original source's license and attribution requirements. + +--- + +**Generated by:** Design Pattern Learner v1.0 +**Date:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} +''' + + return guide + + def _format_colors(self): + """Format colors for guide""" + if not self.patterns.get('design_tokens', {}).get('colors'): + return 'No color patterns found' + + colors = self.patterns['design_tokens']['colors'] + lines = [] + + if 'tailwind' in colors: + lines.append('\n**Tailwind Colors:**') + for color in list(colors['tailwind'])[:10]: + lines.append(f'- `{color}`') + + if 'hex' in colors: + lines.append('\n**Hex Colors:**') + for hex_color in colors['hex'][:10]: + lines.append(f'- `{hex_color}`') + + return '\n'.join(lines) + + def _format_typography(self): + """Format typography for guide""" + if not self.patterns.get('design_tokens', {}).get('typography'): + return 'No typography patterns found' + + typo = self.patterns['design_tokens']['typography'] + lines = [] + + if 'fonts' in typo: + lines.append('\n**Font Families:**') + for font in typo['fonts'][:5]: + lines.append(f'- `{font}`') + + if 'tailwind' in typo: + lines.append('\n**Tailwind Text Classes:**') + for cls in typo['tailwind'][:10]: + lines.append(f'- `{cls}`') + + return '\n'.join(lines) + + def _format_spacing(self): + """Format spacing for guide""" + if not self.patterns.get('design_tokens', {}).get('spacing'): + return 'No spacing patterns found' + + spacing = self.patterns['design_tokens']['spacing'] + lines = [] + + if 'tailwind' in spacing: + lines.append('\n**Tailwind Spacing:**') + for cls in list(spacing['tailwind'])[:10]: + lines.append(f'- `{cls}`') + + return '\n'.join(lines) + + def _format_effects(self): + """Format effects for guide""" + if not self.patterns.get('design_tokens', {}).get('effects'): + return 'No effect patterns found' + + effects = self.patterns['design_tokens']['effects'] + lines = [] + + if 'shadows' in effects: + lines.append('\n**Box Shadows:**') + for shadow in effects['shadows'][:5]: + lines.append(f'- `{shadow}`') + + return '\n'.join(lines) + + def _format_components(self): + """Format components for guide""" + if not self.patterns.get('components'): + return 'No components found' + + library = self.generate_component_library() + lines = [] + + for comp_name, comp_data in library.items(): + lines.append(f'\n### {comp_name.capitalize()}') + lines.append(f'\nFound: {comp_data["count"]} instance(s)') + + for impl in comp_data.get('implementations', [])[:2]: + if self.framework == 'tailwind': + lines.append(f'\n```html') + lines.append(impl.get('html', '')) + lines.append('```') + elif self.framework == 'react': + lines.append(f'\n```jsx') + lines.append(impl.get('code', '')) + lines.append('```') + elif self.framework == 'vue': + lines.append(f'\n```vue') + lines.append(impl.get('code', '')) + lines.append('```') + + return '\n'.join(lines) + + def save_outputs(self, library, design_system, guide): + """Save generated outputs""" + output_dir = os.path.expanduser('~/.claude/skills/design-pattern-learner/data/outputs') + os.makedirs(output_dir, exist_ok=True) + + timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') + + # Save component library + library_file = os.path.join(output_dir, f'library_{self.framework}_{timestamp}.json') + with open(library_file, 'w') as f: + json.dump(library, f, indent=2) + print(f'\n💾 Component library: {library_file}') + + # Save design system + system_file = os.path.join(output_dir, f'design-system_{self.framework}_{timestamp}.json') + with open(system_file, 'w') as f: + json.dump(design_system, f, indent=2) + print(f'💾 Design system: {system_file}') + + # Save implementation guide + guide_file = os.path.join(output_dir, f'implementation-guide_{self.framework}_{timestamp}.md') + with open(guide_file, 'w') as f: + f.write(guide) + print(f'💾 Implementation guide: {guide_file}') + + return library_file, system_file, guide_file + +def main(): + if len(sys.argv) < 3: + print("Usage: python3 generate.py --source --framework ") + print("Example: python3 generate.py --source patterns.json --framework tailwind") + sys.exit(1) + + pattern_file = None + framework = 'tailwind' + + args = sys.argv[1:] + i = 0 + while i < len(args): + if args[i] == '--source' and i + 1 < len(args): + pattern_file = args[i + 1] + i += 2 + elif args[i] == '--framework' and i + 1 < len(args): + framework = args[i + 1].lower() + i += 2 + else: + i += 1 + + if not pattern_file: + print("❌ Error: --source parameter is required") + sys.exit(1) + + if framework not in ['tailwind', 'react', 'vue']: + print(f"⚠️ Warning: Unknown framework '{framework}', using 'tailwind'") + framework = 'tailwind' + + generator = PatternGenerator(pattern_file, framework) + + if not generator.load_patterns(): + sys.exit(1) + + print(f"\n{'='*60}") + print(f"🚀 GENERATING IMPLEMENTATION FOR {framework.upper()}") + print(f"{'='*60}") + + # Generate outputs + library = generator.generate_component_library() + design_system = generator.generate_design_system() + guide = generator.generate_implementation_guide() + + # Save outputs + generator.save_outputs(library, design_system, guide) + + print(f"\n{'='*60}") + print("✅ GENERATION COMPLETE!") + print(f"{'='*60}") + +if __name__ == '__main__': + main() diff --git a/skills/design-pattern-learner/skill.md b/skills/design-pattern-learner/skill.md new file mode 100644 index 00000000..4064ce2d --- /dev/null +++ b/skills/design-pattern-learner/skill.md @@ -0,0 +1,412 @@ +--- +name: design-pattern-learner +description: "Studies and implements web design patterns from external sources. Fetches gists/repositories, analyzes design systems, extracts reusable patterns, and implements with Tailwind CSS. Auto-triggers on design study requests." +priority: 7 +autoTrigger: true +--- + +# Design Pattern Learner + +**Status:** 🟢 **AUTO-ACTIVE** - Automatically triggers when user wants to study/learn from external design sources + +**Auto-invoke:** When user asks to study, learn from, copy, or replicate designs from external sources (gists, repositories, URLs) + +## What This Skill Does + +The Design Pattern Learner skill enables Claude Code to: + +1. **Fetch External Design Sources** - Retrieve gists, repositories, or web pages +2. **Analyze Design Patterns** - Extract layout, styling, animation, and component patterns +3. **Learn Design Systems** - Understand color palettes, typography, spacing, and design tokens +4. **Implement Patterns** - Apply learned patterns with Tailwind CSS or other frameworks +5. **Maintain Attribution** - Track sources and licenses properly + +## Auto-Trigger Patterns + +This skill automatically activates when user says: + +- "study design from [URL/gist/repo]" +- "learn from [source]" +- "implement this design" +- "copy style from" +- "replicate this pattern" +- "analyze this [website/page/component]" +- "extract design patterns from" + +## How It Works + +### Phase 1: Source Acquisition + +``` +Given: URL, gist, or repository reference +1. Fetch the source content +2. Parse HTML/CSS/JS or code files +3. Identify design-related files (styles, components, layouts) +4. Cache for analysis +``` + +### Phase 2: Pattern Analysis + +``` +Extract Design Tokens: +- Colors (primary, secondary, accents) +- Typography (fonts, sizes, weights, line-heights) +- Spacing (margins, padding, gaps) +- Borders (radius, width, style) +- Shadows (box-shadows, text-shadows) + +Identify Components: +- Buttons, cards, forms, modals, navigation +- Layout structures (grids, flexbox, containers) +- Animations and transitions +- Responsive breakpoints + +Detect Patterns: +- Design system usage +- Component variants +- Hover/active states +- Dark mode support +``` + +### Phase 3: Pattern Extraction + +``` +Create Pattern Library: +1. Document each component with: + - HTML structure + - CSS/Tailwind classes + - Design tokens used + - Variations and states + - Usage examples + +2. Generate reusable code: + - Tailwind component snippets + - Custom CSS when needed + - JavaScript for interactions +``` + +### Phase 4: Implementation + +``` +Apply to User Project: +1. Match user's tech stack (Tailwind, CSS-in-JS, etc.) +2. Convert patterns to user's framework +3. Integrate with existing design system +4. Provide implementation guidance +``` + +## Usage Examples + +### Example 1: Study from Gist + +``` +User: "Study the design patterns from https://gist.github.com/ivanfioravanti/abc123" + +Skill executes: +1. Fetches gist content +2. Analyzes HTML/CSS structure +3. Extracts design tokens +4. Documents components found +5. Creates pattern library +6. Shows how to implement in user's project + +Output: +- Design token summary (colors, fonts, spacing) +- Component catalog with code +- Implementation guide for user's stack +- Attribution to original source +``` + +### Example 2: Replicate Component + +``` +User: "Replicate this hero section from https://example.com" + +Skill executes: +1. Fetches the page +2. Isolates hero section +3. Analyzes structure and styling +4. Extracts responsive behavior +5. Creates Tailwind implementation + +Output: +- Complete hero component code +- Design tokens used +- Responsive breakpoints +- Animation effects +``` + +### Example 3: Learn Design System + +``` +User: "Learn the design system from this repository" + +Skill executes: +1. Scans repository for design files +2. Extracts design tokens +3. Maps components to patterns +4. Creates design system documentation + +Output: +- Design system overview +- Component library +- Design token reference +- Usage guidelines +``` + +## Analysis Capabilities + +### Design Token Extraction + +**Colors:** +- Primary/secondary/tertiary palettes +- Semantic colors (success, warning, error) +- Gradient definitions +- Dark mode variants + +**Typography:** +- Font families +- Size scale (text-xs to text-9xl) +- Weight scale (100-900) +- Line-height ratios +- Letter-spacing + +**Spacing:** +- Spacing scale (0-96) +- Margin/padding patterns +- Gap values for flex/grid +- Container sizing + +**Effects:** +- Box shadows (sm, md, lg, xl, 2xl) +- Border radius scale +- Opacity levels +- Blur effects + +### Component Detection + +**UI Elements:** +- Buttons (variants, sizes, states) +- Cards (layouts, effects) +- Forms (inputs, labels, validation) +- Navigation (menus, breadcrumbs, tabs) +- Modals/overlays +- Lists/tables +- Alerts/badges + +**Layout Patterns:** +- Container systems +- Grid layouts +- Flexbox patterns +- Responsive breakpoints +- Header/footer structures + +### Animation Analysis + +**Transitions:** +- Duration/timing functions +- Easing curves +- Transform patterns +- Opacity fades + +**Interactions:** +- Hover effects +- Active states +- Focus states +- Loading animations + +## Output Formats + +### Pattern Documentation + +```markdown +## [Component Name] + +**Source:** [URL/Attribution] +**License:** [License if applicable] + +### Design Tokens +- Colors: primary-500, gray-900 +- Spacing: 4, 8, 16, 24, 32 +- Radius: rounded-lg + +### Structure +```html +[HTML structure] +``` + +### Tailwind Implementation +```html +[Tailwind classes] +``` + +### Variants +- Default +- Hover +- Active +- Disabled +``` + +### Implementation Guide + +```markdown +## Implementation for [Your Stack] + +### Prerequisites +- Tailwind CSS v3+ +- Required plugins + +### Installation +1. Copy component to `components/` +2. Add to Tailwind config if needed +3. Import and use + +### Customization +- Modify colors in config +- Adjust spacing scale +- Update breakpoints +``` + +## Integration with Other Skills + +**Works alongside:** +- `ui-ux-pro-max` - Provides design guidance and best practices +- `codebase-indexer` - Finds relevant files in user's project +- `auto-dispatcher` - Coordinates with other agents + +**Trigger order:** +1. User mentions external design source +2. `design-pattern-learner` activates +3. Fetches and analyzes source +4. `ui-ux-pro-max` provides design guidance +5. `codebase-indexer` finds implementation location +6. Generates implementation code + +## Best Practices + +### Attribution +- Always credit original sources +- Note licenses when applicable +- Link to original implementation + +### Adaptation +- Adapt to user's design system +- Match user's tech stack +- Respect user's preferences +- Maintain consistency + +### Quality +- Test responsive behavior +- Ensure accessibility +- Validate performance +- Check browser compatibility + +## Error Handling + +**Source unavailable:** +- Provide alternative approach +- Suggest similar patterns +- Offer manual input option + +**Complex design:** +- Break into smaller components +- Analyze incrementally +- Provide step-by-step guide + +**License restrictions:** +- Note license terms +- Suggest alternatives +- Create inspired version + +## Commands + +### Analyze URL +```bash +# Direct URL analysis +python3 skills/design-pattern-learner/scripts/analyze.py "https://example.com" + +# Gist analysis +python3 skills/design-pattern-learner/scripts/analyze.py "https://gist.github.com/user/id" + +# Repository analysis +python3 skills/design-pattern-learner/scripts/analyze.py "https://github.com/user/repo" +``` + +### Extract Component +```bash +# Extract specific component +python3 skills/design-pattern-learner/scripts/extract.py "https://example.com" --component "hero" + +# Extract multiple components +python3 skills/design-pattern-learner/scripts/extract.py "https://example.com" --components "hero,footer,nav" +``` + +### Generate Implementation +```bash +# Generate for Tailwind +python3 skills/design-pattern-learner/scripts/generate.py --source "pattern.json" --framework "tailwind" + +# Generate for React +python3 skills/design-pattern-learner/scripts/generate.py --source "pattern.json" --framework "react" + +# Generate for Vue +python3 skills/design-pattern-learner/scripts/generate.py --source "pattern.json" --framework "vue" +``` + +## Data Storage + +**Pattern Library:** `~/.claude/skills/design-pattern-learner/data/patterns/` +- JSON files for learned patterns +- Indexed by source URL +- Version controlled + +**Source Cache:** `~/.claude/skills/design-pattern-learner/data/sources/` +- Cached fetched content +- HTML/CSS/JS files +- Timestamped for refresh + +**Learning Log:** `~/.claude/skills/design-pattern-learner/learning-history.jsonl` +- Record of all sources studied +- Patterns extracted +- Implementation success rate + +## Performance + +**Typical analysis time:** +- Simple component: 5-10 seconds +- Full page: 15-30 seconds +- Design system: 30-60 seconds + +**Cache benefits:** +- Reuse previously analyzed sources +- Incremental updates only +- Pattern matching across sources + +## Contributing Patterns + +**To add new pattern sources:** +1. Verify license compatibility +2. Test extraction quality +3. Document pattern usage +4. Add to pattern library + +**Pattern quality criteria:** +- Modern and current +- Well-structured code +- Responsive design +- Accessible implementation +- Clear documentation + +## Version History + +**v1.0.0** - Initial release +- External source fetching +- Pattern analysis +- Design token extraction +- Component cataloging +- Implementation generation +- Attribution tracking + +--- + +**Remember:** Always respect licenses and attribute sources appropriately. This skill is for learning and inspiration, not for copying proprietary designs without permission.