React Component Generator
Create components that follow this project's conventions and patterns.
Component Structure
Each component needs three files:
code
src/components/
├── ComponentName.tsx # Component implementation
├── ComponentName.module.css # Scoped styles
└── __tests__/
└── ComponentName.test.tsx # Tests
Component Template
TypeScript Component (ComponentName.tsx)
tsx
import React from 'react'
import * as styles from './ComponentName.module.css'
interface ComponentNameProps {
// Define props here
title: string
onClick?: () => void
children?: React.ReactNode
}
const ComponentName = ({ title, onClick, children }: ComponentNameProps) => {
return (
<div className={styles.container}>
<h2 className={styles.title}>{title}</h2>
{children}
{onClick && (
<button onClick={onClick} className={styles.button}>
Click me
</button>
)}
</div>
)
}
export default ComponentName
CSS Module (ComponentName.module.css)
css
.container {
/* Component wrapper styles */
}
.title {
/* Title styles */
}
.button {
/* Button styles */
}
Test File (__tests__/ComponentName.test.tsx)
tsx
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import ComponentName from '../ComponentName'
describe('ComponentName', () => {
it('renders title correctly', () => {
render(<ComponentName title="Test Title" />)
expect(screen.getByText('Test Title')).toBeInTheDocument()
})
it('renders children when provided', () => {
render(
<ComponentName title="Title">
<span>Child content</span>
</ComponentName>
)
expect(screen.getByText('Child content')).toBeInTheDocument()
})
it('calls onClick when button is clicked', () => {
const handleClick = jest.fn()
render(<ComponentName title="Title" onClick={handleClick} />)
fireEvent.click(screen.getByRole('button'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
})
Conventions
TypeScript
- •Define props interface above component (or in
src/types/index.tsif shared) - •Use functional components with arrow functions
- •Prefix unused variables with
_ - •No semicolons (Prettier config)
- •Single quotes for imports
Styling
- •Always use CSS Modules (
*.module.css) - •Import as:
import * as styles from './Component.module.css' - •Use camelCase for class names in CSS
- •No inline styles unless dynamically computed
Props Interface
- •Export interface to
src/types/index.tsif used by multiple components - •Use
React.ReactNodefor children - •Make optional props explicit with
?
File Naming
- •PascalCase for component files:
GalleryImage.tsx - •Match component name exactly
- •CSS module matches component:
GalleryImage.module.css
Checklist Before Completion
- •Component file created with proper TypeScript types
- •CSS Module created (even if minimal)
- •Test file created with basic coverage
- •Props interface exported if needed elsewhere
- •Run
make testto verify tests pass - •Run
make lintto verify no linting errors