Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: extract-ui-component description: Extract reusable UI components from inline patterns. Covers component design, TypeScript props, Storybook stories, refactoring strategy, and best practices for creating shared UI primitives.
Skill: Extract UI Component
Extract reusable React components from inline patterns found in the codebase.
When to Use
- You notice a UI pattern repeated 2+ times across different files
- A component has grown too large and contains extractable sub-patterns
- The component registry flags patterns as "needs extraction"
When NOT to Use
- The pattern appears only once (no reuse benefit)
- The pattern is already a component in the registry
8-Step Workflow
Step 1: Analyze Existing Patterns
Before extracting, find 3-5 instances of the pattern in the codebase:
# Search for common button patternsgrep -rn "className.*btn\|className.*button" src/ --include="*.tsx" | head -20# Search for card-like patternsgrep -rn "className.*card\|className.*rounded.*shadow" src/ --include="*.tsx" | head -20
Document:
- Where each instance appears (file + line)
- What props/data each instance uses
- How instances differ from each other
- Common vs unique aspects
Step 2: Design Component API
Based on the pattern analysis:
- Identify the common interface — what props are shared across all instances
- Identify variants — how instances differ (use discriminated unions for structural differences)
- Design the props interface — extend
React.HTMLAttributes<HTMLElement>for native HTML compatibility
// Good: discriminated union for structural variantstype CardProps =| { variant: 'simple'; title: string; children: React.ReactNode }| { variant: 'media'; title: string; image: string; children: React.ReactNode };// Good: extend HTML attributesinterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {variant?: 'primary' | 'secondary' | 'ghost';size?: 'sm' | 'md' | 'lg';}
Step 3: Implement Component
Create the component following the modlet pattern:
ComponentName/├── index.ts├── ComponentName.tsx├── ComponentName.test.tsx├── ComponentName.stories.tsx└── types.ts (optional)
Guidelines:
- Accept
classNameprop and merge with internal classes usingcn() - Use semantic HTML elements
- Include ARIA attributes for accessibility
- Handle all variants from Step 2
Step 4: Create Storybook Story
Create stories covering:
- Default state
- Each variant
- Each size (if applicable)
- Interactive states (hover, focus, disabled)
- With and without optional props
Step 5: Test in Storybook
Visually verify each story renders correctly.
Step 6: Create Barrel Export
Add re-exports in index.ts:
export { ComponentName } from './ComponentName';export type { ComponentNameProps } from './types';
Step 7: Refactor Existing Code
Replace inline patterns one file at a time:
- Import the new component
- Replace the inline pattern with the component
- Verify the page still works
- Commit after each file
Do not refactor all files at once. One file at a time reduces risk.
Step 8: Update Component Registry
Add the new component to the component registry (if one exists).
Accessibility Guidelines
- Use semantic HTML (
<button>,<nav>,<main>, not<div>with click handlers) - Include
aria-labelfor icon-only buttons - Ensure keyboard navigation works (tab, enter, escape)
- Use
roleattributes when semantic HTML isn't sufficient - Test with screen reader in Storybook
Common Pitfalls
- ❌ Don't create overly generic components (a component that does everything does nothing well)
- ❌ Don't forget to handle the
classNameprop for customization - ❌ Don't skip the pattern analysis step — extracting from one instance leads to a bad API
- ❌ Don't refactor all files at once
- ✅ Do analyze 3-5 instances before designing the API
- ✅ Do use discriminated unions for structural variants
- ✅ Do extend HTML attributes for native compatibility
- ✅ Do refactor one file at a time
Checklist
- [ ] 3-5 existing pattern instances analyzed
- [ ] Props interface designed with variants
- [ ] Component implemented with modlet structure
- [ ] Storybook stories cover all variants
- [ ] Stories visually verified
- [ ] Barrel export created
- [ ] Existing code refactored (one file at a time)
- [ ] Component registry updated
- [ ] Accessibility verified