---
globs: src/components/**/*.tsx
---
# Component Patterns
## Component Structure
### File Organization
- Place reusable components in `src/components/`
- Use PascalCase for component files: `ComponentName.tsx`
- Group related components in subdirectories when needed
### Component Template
```typescript
import { cn } from '@/lib/utils'
interface ComponentProps {
className?: string
children?: React.ReactNode
// Other props
}
export function ComponentName({
className,
children,
...props
}: ComponentProps) {
return (
{children}
)
}
```
## shadcn/ui Integration
### Using shadcn/ui Components
```typescript
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
export function ProjectCard({ project }: { project: Project }) {
return (
{project.title}
{project.category}
)
}
```
### Extending shadcn/ui Components
```typescript
// Create wrapper components for common patterns
import { Button } from '@/components/ui/button'
import { cn } from '@/lib/utils'
interface PrimaryButtonProps extends React.ComponentProps {
loading?: boolean
}
export function PrimaryButton({
loading,
className,
children,
...props
}: PrimaryButtonProps) {
return (
)
}
```
## Animation Patterns
### Framer Motion Usage
```typescript
import { motion } from 'framer-motion'
export function AnimatedCard({ children }: { children: React.ReactNode }) {
return (
{children}
)
}
```
## Component Composition
### Compound Components
```typescript
// Parent component
export function Accordion({ children }: { children: React.ReactNode }) {
return {children}
}
// Child components
export function AccordionItem({ children }: { children: React.ReactNode }) {
return {children}
}
export function AccordionTrigger({ children }: { children: React.ReactNode }) {
return
}
// Usage
Title
Content
```
## Props and TypeScript
### Interface Patterns
```typescript
// Use descriptive interface names
interface ProjectCardProps {
project: Project
variant?: 'default' | 'featured'
showDescription?: boolean
onSelect?: (project: Project) => void
}
// Use React.ComponentProps for extending HTML elements
interface CustomButtonProps extends React.ComponentProps<'button'> {
variant?: 'primary' | 'secondary'
size?: 'sm' | 'md' | 'lg'
}
```
## Styling Guidelines
1. **Tailwind First**: Use utility classes before custom CSS
2. **Conditional Classes**: Use `cn()` utility for conditional styling
3. **Responsive Design**: Mobile-first approach with responsive utilities
4. **Dark Theme**: Ensure all components work in dark mode
5. **Accessibility**: Include proper ARIA labels and semantic HTML