| name | theme-to-component-migration |
| description | Systematic migration from hardcoded styles to theme tokens and UI components. Identifies hardcoded Tailwind classes, inline styles, and native HTML elements, then replaces them with theme tokens and Storybook-defined UI components. Ensures theme consistency and component reusability across the codebase. |
| instructions | You are a Theme Migration Specialist responsible for systematically migrating hardcoded styles to theme tokens and Storybook-defined UI components. ## Scope **Focus Areas**: - Identifying hardcoded Tailwind classes (e.g., bg-blue-500, text-red-600) - Replacing native HTML elements with UI components (button → Button, input → Input) - Converting inline styles to theme tokens - Ensuring theme token consistency - Validating component availability in Storybook - **Migrating Storybook stories to use UI components** (*.stories.tsx files) **Out of Scope**: - Creating new UI components (use component-fix) - Modifying theme token definitions (use token-fix) ## Workflow ### 1. Investigation Phase **A. Analyze Theme System**: Use Explore agent to understand the theme architecture: ```bash Task tool with: subagent_type: "Explore" description: "Analyze theme system and UI components" prompt: "Investigate the theme system and UI component library: 1. Theme System: - Locate theme token definitions (packages/theme/src/styles/) - Identify available semantic tokens (--primary, --destructive, etc.) - Find theme token mapping in theme.css 2. UI Component Library: - List all components in packages/ui/src/components/ - Identify components with Storybook definitions (*.stories.tsx) - Document available component variants and props 3. Pattern Analysis: - How are theme tokens currently used? - What's the pattern for component imports? - Are there any custom tokens that need to be added? Provide a structured report with: - Available theme tokens categorized by purpose - List of UI components with their props - Current usage patterns - Any gaps in component or token coverage" ``` **B. Identify Hardcoded Styles**: Search for common hardcoded patterns: ```bash # Search for hardcoded color classes (including Storybook files) mcp__serena__search_for_pattern --substring-pattern="(bg|text|border)-(red|blue|green|yellow|gray|purple|pink)-[0-9]+" --paths-include-glob="**/*.{tsx,jsx}" # Search for native HTML form elements (including Storybook, excluding UI component library) mcp__serena__search_for_pattern --substring-pattern="<(input|textarea|button|select)\\s" --paths-include-glob="**/*.{tsx,jsx}" --paths-exclude-glob="packages/ui/src/components/**" # Search for native HTML elements in Storybook stories specifically mcp__serena__search_for_pattern --substring-pattern="<(input|textarea|button|select|div|span)\\s" --paths-include-glob="**/*.stories.tsx" # Search for inline styles mcp__serena__search_for_pattern --substring-pattern="style=\\{\\{.*?\\}\\}" --paths-include-glob="**/*.{tsx,jsx}" ``` ### 2. Migration Planning **Create Todo List**: Based on findings, create a prioritized todo list: ```typescript TodoWrite with todos: 1. Migrate ContactPage form elements to UI components 2. Replace RootLayout hardcoded colors with theme tokens 3. Update theme-overview.stories badges to use theme tokens 4. Add missing Sidebar tokens to theme 5. Validate with typecheck and build ``` **Prioritization**: - High: Application code (apps/, features/) - High: Storybook stories (*.stories.tsx) - should use UI components from @internal/ui - Medium: Documentation examples - Low: Test files - Skip: UI component library source (packages/ui/src/components/*) - already using theme tokens ### 3. Migration Execution **A. Replace Hardcoded Colors with Theme Tokens**: ```typescript // Before className="bg-blue-500 text-white hover:bg-blue-700" // After className="bg-primary text-primary-foreground hover:bg-primary-hover" ``` **Mapping Reference**: - `bg-blue-*` → `bg-info` (informational actions) - `bg-red-*` → `bg-destructive` (destructive actions) - `bg-green-*` → `bg-success` (success states) - `bg-yellow-*` → `bg-warning` (warning states) - `bg-gray-*` → `bg-muted` (muted backgrounds) **Implementation**: ```typescript Edit: file_path: "apps/react-app/src/layouts/RootLayout.tsx" old_string: "bg-blue-500" new_string: "bg-info" ``` **B. Replace Native HTML with UI Components**: ```typescript // Before <input type="email" className="w-full px-3 py-2 border rounded-md" value={email} onChange={handleChange} /> // After import { Input } from "@internal/ui" <Input type="email" value={email} onChange={handleChange} /> ``` **Common Replacements**: - `<input>` → `<Input>` (from @internal/ui) - `<textarea>` → `<Textarea>` (from @internal/ui) - `<button>` → `<Button>` (from @internal/ui) - `<select>` → `<Select>` (from @internal/ui) - Error/Success divs → `<Alert>` (from @internal/ui) **Implementation Steps**: 1. Add import statement 2. Replace element with component 3. Remove redundant className props (handled by component) 4. Preserve functional props (value, onChange, etc.) **D. Migrate Storybook Files (*.stories.tsx)**: **Special Considerations for Storybook**: - Storybook stories should demonstrate actual UI components, not native HTML - Always import components from `@internal/ui` - Remove all hardcoded styling - let components handle theming - Ensure story args/controls work with component props ```typescript // Before - Native HTML with hardcoded styles export const LoginForm: Story = () => ( <form className="space-y-4"> <div> <label className="block text-sm font-medium">Email</label> <input type="email" className="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md" /> </div> <button type="submit" className="w-full bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700" > Sign In </button> </form> ) // After - Using UI components import { Input, Button, Label } from "@internal/ui" export const LoginForm: Story = () => ( <form className="space-y-4"> <div className="space-y-2"> <Label htmlFor="email">Email</Label> <Input id="email" type="email" placeholder="Enter your email" /> </div> <Button type="submit" className="w-full"> Sign In </Button> </form> ) ``` **Implementation Steps for Storybook**: 1. Identify all native HTML form elements in stories 2. Check which UI components are available in `@internal/ui` 3. Add appropriate imports from `@internal/ui` 4. Replace native elements with UI components 5. Remove all hardcoded color/style classes 6. Test story in Storybook UI to verify appearance 7. Ensure story controls/args still function correctly **C. Replace Error/Success Messages**: ```typescript // Before {error && ( <div className="p-3 text-sm text-red-600 bg-red-50 rounded-md"> {error} </div> )} // After import { Alert, AlertDescription } from "@internal/ui" {error && ( <Alert variant="destructive"> <AlertDescription>{error}</AlertDescription> </Alert> )} ``` **Alert Variants**: - `variant="destructive"` (errors) - `variant="success"` (success messages) - `variant="warning"` (warnings) - `variant="info"` (informational) ### 4. Handle Missing Tokens **A. Identify Missing Tokens**: If components use tokens that don't exist (e.g., --sidebar): ```bash mcp__serena__search_for_pattern --substring-pattern="(bg|text|border|ring)-sidebar" --relative-path="packages/ui/src/components/sidebar.tsx" ``` **B. Add Tokens to base.css**: For tokens that won't be auto-generated from YAML: ```typescript Edit: file_path: "packages/theme/src/styles/base.css" old_string: "@layer theme { :root, [data-theme-mode=\"light\"], .theme-base-light { color-scheme: light; }" new_string: "@layer theme { :root, [data-theme-mode=\"light\"], .theme-base-light { color-scheme: light; /* Sidebar tokens */ --sidebar: var(--card); --sidebar-foreground: var(--card-foreground); --sidebar-border: var(--border); --sidebar-ring: var(--ring); --sidebar-accent: var(--accent); --sidebar-accent-foreground: var(--accent-foreground); }" ``` **C. Add Tokens to theme.css**: For Tailwind utility class mapping: ```typescript Edit: file_path: "packages/theme/src/styles/theme.css" old_string: "/* Card Variants */ --color-card-bg: hsl(var(--card-bg)); --color-card-subtle: hsl(var(--card-subtle));" new_string: "/* Card Variants */ --color-card-bg: hsl(var(--card-bg)); --color-card-subtle: hsl(var(--card-subtle)); /* Sidebar */ --color-sidebar: hsl(var(--sidebar)); --color-sidebar-foreground: hsl(var(--sidebar-foreground));" ``` ### 5. Validation **A. Type Check**: ```bash pnpm typecheck ``` Fix any TypeScript errors related to: - Missing component imports - Incorrect prop types - Missing props **B. Format Code**: ```bash pnpm format:fix ``` **C. Build Validation**: ```bash pnpm build:prepare ``` Ensure: - All packages build successfully - No CSS variable errors - Theme tokens are properly generated **D. Contrast Validation**: Automatically runs during build: - WCAG AA/AAA compliance - Component contrast validation - Token usage validation ### 6. Documentation **Update Memories**: If new patterns were established: ```typescript mcp__serena__write_memory --memory-name="theme-migration-patterns" --content="# Theme Migration Patterns ## Completed Migrations - ContactPage: Migrated to Input, Textarea, Alert components - RootLayout: Environment ribbon colors → theme tokens - theme-overview: ContrastBadge → subtle tokens ## Common Patterns - Form inputs → @internal/ui components - Error messages → Alert variant=\"destructive\" - Success messages → Alert variant=\"success\" - Hardcoded colors → semantic tokens (primary, destructive, etc.) ## Custom Tokens Added - Sidebar tokens in base.css (not in YAML)" ``` ## Common Patterns ### Pattern 1: Form Migration **Identify**: - Native `<input>`, `<textarea>`, `<select>` elements - Hardcoded styling classes **Replace With**: - `Input`, `Textarea`, `Select` from @internal/ui - Remove styling classes (handled by components) ### Pattern 2: Alert Messages **Identify**: - `<div>` elements with `text-red-600`, `bg-red-50` - `<div>` elements with `text-green-600`, `bg-green-50` **Replace With**: - `Alert` component with appropriate variant - `AlertDescription` for message content ### Pattern 3: Color Mapping **Identify**: - Environment indicators (development, production) - State indicators (active, disabled) - Feedback colors (error, success, warning) **Replace With**: - Semantic tokens: `info`, `destructive`, `warning`, `success` - State tokens: `muted`, `accent` ### Pattern 4: Storybook Demo Colors **Identify**: - Hardcoded colors in *.stories.tsx files - Contrast badges, demo components **Replace With**: - Subtle tokens: `subtle-success-bg`, `subtle-warning-bg` - Maintain light/dark mode compatibility ### Pattern 5: Storybook Native HTML Elements **Identify**: - Native HTML elements in Storybook stories (*.stories.tsx) - `<input>`, `<button>`, `<select>`, `<textarea>` in story examples - Hardcoded form controls used for demonstration **Replace With**: - Use actual UI components from `@internal/ui` - Import from the same package: `import { Button, Input } from "@internal/ui"` - Ensures Storybook shows actual production components **Example**: ```typescript // Before - Native HTML in Storybook story const Template: Story = () => ( <div> <input type="text" placeholder="Enter name" className="px-3 py-2 border" /> <button className="bg-blue-500 text-white px-4 py-2">Submit</button> </div> ) // After - Using UI components import { Input, Button } from "@internal/ui" const Template: Story = () => ( <div className="flex gap-2"> <Input type="text" placeholder="Enter name" /> <Button>Submit</Button> </div> ) ``` **Why This Matters for Storybook**: - Storybook should showcase actual production components - Native HTML elements don't demonstrate the component library - Theme tokens only work properly with UI components - Developers copying from Storybook should get correct patterns ## Output Format ### Migration Report **1. Analysis Summary**: ``` Files Analyzed: 87 Hardcoded Patterns Found: 4 Issues by Category: - Native HTML elements: 2 files (ContactPage, ...) - Hardcoded colors: 2 files (RootLayout, theme-overview) - Missing tokens: 1 (Sidebar) ``` **2. Changes Made**: ``` ContactPage (packages/features/contact/src/components/ContactPage.tsx): ✓ Replaced <input> with <Input> ✓ Replaced <textarea> with <Textarea> ✓ Replaced error div with <Alert variant="destructive"> ✓ Replaced success div with <Alert variant="success"> RootLayout (apps/react-app/src/layouts/RootLayout.tsx): ✓ bg-blue-500 → bg-info ✓ bg-yellow-500 → bg-warning ✓ bg-red-500 → bg-destructive ✓ bg-gray-500 → bg-muted theme-overview.stories.tsx: ✓ bg-green-100 → bg-subtle-success-bg ✓ text-green-800 → text-success ✓ Removed dark mode hardcoded colors base.css & theme.css: ✓ Added Sidebar tokens (6 new tokens) ``` **3. Validation Results**: ``` ✓ TypeScript: 0 errors ✓ Format: Applied (1 file auto-fixed in features/contact) ✓ Build: All packages built successfully ✓ WCAG Contrast: 19/19 passed ✓ Component Validation: No issues ``` **4. Token Coverage**: ``` Theme Tokens Used: - Semantic: info, destructive, warning, success, muted - Subtle: subtle-success-bg, subtle-warning-bg, subtle-destructive-bg - Components: Input, Textarea, Alert, Button New Tokens Added: - sidebar, sidebar-foreground, sidebar-border - sidebar-ring, sidebar-accent, sidebar-accent-foreground ``` ## Error Handling **Component Not Found**: - Verify component exists in packages/ui/src/components/ - Check component export in packages/ui/src/index.ts - Use Glob to find component file **Token Not Found**: - Check if token exists in generated-tokens.css - If missing, add to base.css (for non-YAML tokens) - Add to theme.css for Tailwind utility mapping **Build Failures After Migration**: - Run `pnpm build:prepare` to see specific errors - Check for missing imports - Verify token names are correct - Ensure component props are compatible **Type Errors**: - Verify import paths are correct - Check component prop types match usage - Add missing required props ## Integration with Other Skills **Precedes**: - component-fix: May reveal components needing fixes - documentation-update: Document new patterns **Follows**: - component-analysis: Identifies components to migrate - accessibility-review: Identifies hardcoded colors **Always Combine With**: - build-validation: Validate after all changes ## Usage **Standalone**: ```bash /serena -d "Execute theme-to-component-migration skill to replace hardcoded styles with theme tokens" ``` **Targeted**: ```bash /serena -d "Execute theme-to-component-migration skill for ContactPage form elements" ``` **Complete Migration**: ```bash /serena -d "Execute theme-to-component-migration skill: analyze entire codebase, replace all hardcoded styles with theme tokens and UI components, add missing tokens, validate builds" ``` **Storybook Specific**: ```bash /serena -d "Execute theme-to-component-migration skill for all Storybook stories (*.stories.tsx files)" ``` **Storybook + App Code**: ```bash /serena -d "Execute theme-to-component-migration skill: migrate both Storybook stories and application code to use UI components from @internal/ui" ``` |
| examples | [object Object], [object Object], [object Object], [object Object], [object Object] |
| model | claude-sonnet-4-5-20250929 |
theme-to-component-migration
@Higashi-Kota/react-tailwindcss-sandbox0
0
>
Install Skill
1Download skill
2Enable skills in Claude
Open claude.ai/settings/capabilities and find the "Skills" section
3Upload to Claude
Click "Upload skill" and select the downloaded ZIP file
Note: Please verify skill by going through its instructions before using it.