---
description: Create a new Vue component following ThrillWiki patterns
---
# New Component Workflow
Create a new Vue component following ThrillWiki's design system and conventions.
## Information Gathering
1. **Component Name**: PascalCase (e.g., `ParkCard`, `RatingDisplay`)
2. **Category**:
- `ui/` - Base components (Button, Card, Input)
- `entity/` - Domain-specific (ParkCard, RideCard)
- `forms/` - Form components
- `specialty/` - Complex/unique components
3. **Props**: What data does it receive?
4. **Emits**: What events does it emit?
5. **State**: Does it have internal state?
6. **Variants**: Does it need multiple variants/sizes?
## Component Template
### Base Component Structure
Location: `frontend/components/[category]/ComponentName.vue`
```vue
```
### Entity Card Component
For ParkCard, RideCard, etc.:
```vue
{{ park.status }}
{{ park.name }}
{{ park.city }}, {{ park.country }}
🎢 {{ park.rideCount }} rides
```
### Skeleton Loading Component
Every entity card should have a matching skeleton:
```vue
```
## Variant Pattern (using CVA)
For components with many variants, use class-variance-authority:
```vue
```
## Composable Integration
If component needs shared logic, create a composable:
```typescript
// composables/useUnitDisplay.ts
export function useUnitDisplay() {
const { preferredUnits } = useUserPreferences()
function formatSpeed(kmh: number): string {
if (preferredUnits.value === 'imperial') {
return `${Math.round(kmh * 0.621371)} mph`
}
return `${kmh} km/h`
}
function formatHeight(meters: number): string {
if (preferredUnits.value === 'imperial') {
return `${Math.round(meters * 3.28084)} ft`
}
return `${meters} m`
}
return { formatSpeed, formatHeight }
}
```
## Checklist
After creating the component:
- [ ] TypeScript props are properly defined
- [ ] Component follows design system (colors, spacing, typography)
- [ ] Responsive on all screen sizes
- [ ] Handles loading state (if applicable)
- [ ] Handles empty state (if applicable)
- [ ] Accessible (ARIA labels, keyboard nav)
- [ ] Has matching skeleton component (for async data)
- [ ] Works in dark mode
## Output
Report what was created:
```
Created: frontend/components/[category]/ComponentName.vue
Props: [list of props]
Emits: [list of events]
Related: [any composables or sub-components]
```