Convert HTML/CSS theme templates into reusable React components. Use when: migrating theme files to React, preserving existing CSS structure, handling JavaScript animations with React hooks, decomposing large components.
Procedural workflow for migrating HTML/CSS themes into modular React components with preserved styling and hook-based animation logic.
Create assets subdirectory in src/assets/
src/assets/
├── theme-name/
│ ├── css/ # All CSS files from theme
│ ├── js/ # Original JavaScript files (for reference)
│ └── images/ # Theme demo images and icons
Copy theme files without modification
.css files → assets/theme-name/css/.js files → assets/theme-name/js/ (for reference only)assets/theme-name/images/Import CSS globally in src/main.tsx
import './assets/theme-name/css/main.css'
// ... other theme CSS imports
Analyze HTML structure from theme files
Create component structure respecting class names
src/components/Component template example
// src/components/ThemeCard/ThemeCard.tsx
/**
* ThemeCard - Reusable card component from theme
* Maps to original HTML markup with theme CSS classes
*/
import React from 'react'
interface ThemeCardProps {
title: string
content: string
className?: string
}
export const ThemeCard: React.FC<ThemeCardProps> = ({
title,
content,
className = ''
}) => {
return (
<div className={`theme-card ${className}`}>
<h3 className="theme-card__title">{title}</h3>
<p className="theme-card__content">{content}</p>
</div>
)
}
Identify animations and interactions in original JS files
Create custom hooks for reusable animation logic
// src/hooks/useThemeAnimation.ts
/**
* useThemeAnimation - Handle theme fade/slide animations
* Maps original jQuery animations to React state
*/
import { useState, useCallback } from 'react'
interface UseThemeAnimationOptions {
duration?: number
triggerEvent?: 'click' | 'hover' | 'scroll'
}
export const useThemeAnimation = (
options: UseThemeAnimationOptions = {}
) => {
const { duration = 300 } = options
const [isAnimating, setIsAnimating] = useState(false)
const trigger = useCallback(() => {
setIsAnimating(true)
setTimeout(() => setIsAnimating(false), duration)
}, [duration])
return { isAnimating, trigger }
}
Apply hooks to components
// Use in component:
const { isAnimating, trigger } = useThemeAnimation({ duration: 500 })
return (
<button onClick={trigger}>
<div className={`animated-element ${isAnimating ? 'is-active' : ''}`}>
Content
</div>
</button>
)
Monitor component file size
Create subdirectory for large components
src/components/
├── ComplexFeature/
│ ├── index.tsx # Parent container component
│ ├── ComplexFeature.tsx # Main export
│ ├── SubComponent1.tsx
│ ├── SubComponent2.tsx
│ └── useComplexLogic.ts
Add header comment to each sub-component
/**
* SubComponent1
*
* Part of ComplexFeature feature. Handles [specific responsibility].
* Keeps parent component under 600-line limit.
*/
Extract hooks for reusable logic
Use the Quality Checklist to verify:
src/
├── assets/
│ └── bootstrap-theme/
│ ├── css/
│ │ ├── bootstrap.css
│ │ ├── theme.css
│ │ └── components.css
│ ├── js/
│ │ └── animations.js (reference only)
│ └── images/
├── components/
│ ├── Navigation/
│ │ └── Navigation.tsx
│ ├── HeroSection/
│ │ └── HeroSection.tsx
│ ├── CardGrid/
│ │ ├── index.tsx
│ │ ├── CardGrid.tsx
│ │ ├── Card.tsx
│ │ └── useCardAnimation.ts
│ └── Footer/
│ └── Footer.tsx
├── hooks/
│ ├── useThemeAnimation.ts
│ ├── useScrollAnimation.ts
│ └── useModalToggle.ts
└── main.tsx (imports all theme CSS)
const [isActive, setIsActive] = useState(false)
return (
<div className={`theme-element ${isActive ? 'is-active' : ''}`}>
{/* Respects original theme's is-active CSS state */}
</div>
)
// Original: $('#element').on('click', function() { ... })
// React:
const handleClick = useCallback(() => {
// animation or state change
}, [])
return <element onClick={handleClick} className="original-class" />
const [formData, setFormData] = useState({})
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
// Trigger validation or animations via CSS classes
}
main.tsx