Files
gh-jeremylongshore-claude-c…/commands/component-generator.md
2025-11-30 08:20:34 +08:00

343 lines
6.7 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: Generate React components from descriptions with TypeScript and tests
shortcut: cg
category: frontend
difficulty: beginner
estimated_time: 2-5 minutes
---
# Component Generator
Generates production-ready React components from natural language descriptions, including TypeScript types, styling, and tests.
## What This Command Does
**Component Generation:**
- Creates React component with TypeScript
- Generates prop types and interfaces
- Adds basic styling (CSS modules or Tailwind)
- Creates test file (React Testing Library)
- Includes JSDoc comments
- Follows React best practices
**Output:** Complete component with types, styles, and tests
**Time:** 2-5 minutes
---
## Usage
```bash
# Generate component from description
/component-generator "Create a Card component with image, title, description, and action button"
# Shortcut
/cg "Button component with loading state and icon support"
# Specify framework/style
/cg "Modal dialog with animations" --style tailwind --test vitest
# Generate with directory
/cg "UserProfile component" --output src/components/UserProfile
```
---
## Example Output
**Input:**
```
/cg "Create a Button component with variants (primary, secondary, ghost), sizes (sm, md, lg), loading state, and icon support"
```
**Generated Files:**
**Button.tsx:**
```tsx
import { ButtonHTMLAttributes, ReactNode } from 'react'
import styles from './Button.module.css'
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
/** Button visual variant */
variant?: 'primary' | 'secondary' | 'ghost'
/** Button size */
size?: 'sm' | 'md' | 'lg'
/** Show loading spinner */
loading?: boolean
/** Icon to display before text */
icon?: ReactNode
/** Button content */
children: ReactNode
}
/**
* Button component with multiple variants and sizes
*
* @example
* ```tsx
* <Button variant="primary" size="md" onClick={handleClick}>
* Click me
* </Button>
* ```
*/
export function Button({
variant = 'primary',
size = 'md',
loading = false,
icon,
children,
disabled,
className = '',
...props
}: ButtonProps) {
return (
<button
className={`${styles.button} ${styles[variant]} ${styles[size]} ${className}`}
disabled={disabled || loading}
aria-busy={loading}
{...props}
>
{loading ? (
<span className={styles.spinner} aria-label="Loading" />
) : (
<>
{icon && <span className={styles.icon}>{icon}</span>}
{children}
</>
)}
</button>
)
}
```
**Button.module.css:**
```css
.button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
border: none;
border-radius: 0.375rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Variants */
.primary {
background: #3b82f6;
color: white;
}
.primary:hover:not(:disabled) {
background: #2563eb;
}
.secondary {
background: #e5e7eb;
color: #374151;
}
.ghost {
background: transparent;
color: #3b82f6;
}
/* Sizes */
.sm {
padding: 0.5rem 1rem;
font-size: 0.875rem;
}
.md {
padding: 0.75rem 1.5rem;
font-size: 1rem;
}
.lg {
padding: 1rem 2rem;
font-size: 1.125rem;
}
.spinner {
display: inline-block;
width: 1em;
height: 1em;
border: 2px solid currentColor;
border-right-color: transparent;
border-radius: 50%;
animation: spin 0.6s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
```
**Button.test.tsx:**
```tsx
import { render, screen, fireEvent } from '@testing-library/react'
import { Button } from './Button'
describe('Button', () => {
it('renders button with text', () => {
render(<Button>Click me</Button>)
expect(screen.getByRole('button')).toHaveTextContent('Click me')
})
it('handles click events', () => {
const handleClick = jest.fn()
render(<Button onClick={handleClick}>Click</Button>)
fireEvent.click(screen.getByRole('button'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
it('shows loading state', () => {
render(<Button loading>Submit</Button>)
const button = screen.getByRole('button')
expect(button).toHaveAttribute('aria-busy', 'true')
expect(button).toBeDisabled()
})
it('disables button when disabled prop is true', () => {
render(<Button disabled>Disabled</Button>)
expect(screen.getByRole('button')).toBeDisabled()
})
it('renders with icon', () => {
const icon = <span data-testid="icon"></span>
render(<Button icon={icon}>With Icon</Button>)
expect(screen.getByTestId('icon')).toBeInTheDocument()
})
it('applies correct variant classes', () => {
const { rerender } = render(<Button variant="primary">Primary</Button>)
expect(screen.getByRole('button')).toHaveClass('primary')
rerender(<Button variant="secondary">Secondary</Button>)
expect(screen.getByRole('button')).toHaveClass('secondary')
})
})
```
---
## Component Templates
### Common Components Generated
**1. Card Component:**
```tsx
<Card
image="/product.jpg"
title="Product Name"
description="Product description"
action={<Button>Buy Now</Button>}
/>
```
**2. Modal Component:**
```tsx
<Modal
isOpen={isOpen}
onClose={handleClose}
title="Confirm Action"
>
<p>Are you sure?</p>
</Modal>
```
**3. Form Field Component:**
```tsx
<FormField
label="Email"
type="email"
error={errors.email}
required
/>
```
**4. Dropdown Component:**
```tsx
<Dropdown
items={options}
value={selected}
onChange={handleChange}
placeholder="Select option"
/>
```
---
## Features
### Accessibility Built-In
- Semantic HTML elements
- ARIA attributes where needed
- Keyboard navigation support
- Focus management
- Screen reader announcements
### TypeScript Support
- Full type definitions
- Prop validation
- IntelliSense support
- Generic types where appropriate
### Testing Included
- Unit tests with React Testing Library
- Accessibility tests
- User interaction tests
- Edge case coverage
### Styling Options
- CSS Modules (default)
- Tailwind CSS
- Styled Components
- Emotion
- Plain CSS
---
## Best Practices Applied
**Component Structure:**
- Single responsibility
- Composable design
- Prop drilling avoided
- Performance optimized (React.memo where beneficial)
**Code Quality:**
- ESLint compliant
- Prettier formatted
- TypeScript strict mode
- JSDoc comments
**Testing:**
- 80%+ code coverage
- User-centric tests (not implementation details)
- Accessibility assertions
- Happy path + edge cases
---
## Related Commands
- `/css-utility-generator` - Generate utility CSS classes
- React Specialist (agent) - React architecture guidance
- UI/UX Expert (agent) - Design review
---
**Generate components in seconds. Ship features faster.**