veza/apps/web/src/components/COMPONENT_USAGE.md

461 lines
9.5 KiB
Markdown
Raw Normal View History

# Component Usage Guide
**Last Updated**: 2025-01-27
**Purpose**: Guide for when and how to use design system components
## Table of Contents
1. [Button](#button)
2. [Card](#card)
3. [Input](#input)
4. [Select](#select)
5. [Dialog](#dialog)
6. [Alert](#alert)
7. [Badge](#badge)
8. [Best Practices](#best-practices)
---
## Button
**Location**: `@/components/ui/button`
**Import**: `import { Button } from '@/components/ui/button'`
### When to Use
**DO use Button component for:**
- All interactive buttons (primary actions, secondary actions, navigation)
- Icon buttons
- Link-style buttons
- Destructive actions (delete, remove)
**DON'T use:**
- Native `<button>` elements (ESLint will warn)
- Custom button implementations with inline styles
### Variants
| Variant | Use Case | Example |
|---------|----------|---------|
| `default` | Primary actions, main CTAs | "Save", "Submit", "Upload" |
| `outline` | Secondary actions, outlined style | "Cancel", "Back", inactive states |
| `ghost` | Tertiary actions, minimal style | Icon buttons, menu items, subtle actions |
| `destructive` | Destructive actions | "Delete", "Remove", "Clear" |
| `secondary` | Secondary actions with background | Alternative to outline |
| `link` | ~~Link-style buttons~~ (removed - use `ghost` with underline) | ~~"View all", "Learn more"~~ |
**Note**: Variants `neon`, `glass`, `premium`, and `link` have been removed. Use `default`, `outline`, or `ghost` instead.
### Sizes
| Size | Use Case |
|------|----------|
| `default` | Standard buttons (h-10) |
| `sm` | Compact buttons, inline actions (h-8) |
| `lg` | Prominent CTAs (h-12) |
| `icon` | Icon-only buttons (h-10 w-10) |
### Examples
```tsx
// Primary action
<Button variant="default" onClick={handleSave}>
Save Changes
</Button>
// Secondary action
<Button variant="outline" onClick={handleCancel}>
Cancel
</Button>
// Icon button
<Button variant="ghost" size="icon" onClick={handleEdit}>
<Edit className="w-4 h-4" />
</Button>
// Destructive action
<Button variant="destructive" onClick={handleDelete}>
Delete Track
</Button>
// Link-style (use ghost with underline)
<Button variant="ghost" className="text-kodo-cyan hover:underline" onClick={handleViewAll}>
View all tracks
</Button>
```
### Common Patterns
**Button Groups:**
```tsx
<div className="flex gap-2">
<Button variant="outline">Cancel</Button>
<Button variant="default">Save</Button>
</div>
```
**Icon with Text:**
```tsx
<Button variant="ghost" size="sm">
<Heart className="w-4 h-4" />
<span>Like</span>
</Button>
```
---
## Card
**Location**: `@/components/ui/card`
**Import**: `import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@/components/ui/card'`
### When to Use
**DO use Card component for:**
- Content containers
- Dashboard widgets
- Feature cards
- Data display sections
**DON'T use:**
- Custom card implementations
- Legacy Card component from `@/components/base/Card`
- Invalid `variant` prop (Card doesn't support variants)
### Structure
```tsx
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Optional description</CardDescription>
</CardHeader>
<CardContent>
{/* Main content */}
</CardContent>
<CardFooter>
{/* Footer actions */}
</CardFooter>
</Card>
```
### Examples
```tsx
// Simple card
<Card>
<CardHeader>
<CardTitle>Track Statistics</CardTitle>
</CardHeader>
<CardContent>
<p>Total plays: 1,234</p>
</CardContent>
</Card>
// Card with footer actions
<Card>
<CardHeader>
<CardTitle>Settings</CardTitle>
<CardDescription>Manage your preferences</CardDescription>
</CardHeader>
<CardContent>
{/* Settings form */}
</CardContent>
<CardFooter>
<Button variant="default">Save</Button>
</CardFooter>
</Card>
```
### Styling
- Card uses className-based styling (no variants)
- Use `className` prop for custom styling
- Default styles: rounded-2xl, border, background, shadow, hover effects
---
## Input
**Location**: `@/components/ui/input`
**Import**: `import { Input } from '@/components/ui/input'`
### When to Use
**DO use Input component for:**
- Text inputs
- Number inputs
- Email inputs
- Password inputs
- Search inputs
**DON'T use:**
- Native `<input>` elements (for consistency)
- Custom input implementations (unless specialized like AuthInput, ChatInput)
### Examples
```tsx
// Basic input
<Input
type="text"
placeholder="Enter track title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
// With label
<div className="space-y-2">
<Label htmlFor="title">Track Title</Label>
<Input
id="title"
type="text"
placeholder="Enter track title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</div>
// Disabled state
<Input
type="text"
placeholder="Disabled input"
disabled
/>
```
### Styling
- Input uses consistent styling: rounded-lg, border, background, focus states
- Focus state: border-kodo-cyan
- Disabled state: opacity-50, cursor-not-allowed
---
## Select
**Location**: `@/components/ui/select`
**Import**: `import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@/components/ui/select'`
### When to Use
**DO use Select component for:**
- Dropdown selections
- Filter options
- Sort options
- Choice selections
**DON'T use:**
- Native `<select>` elements (for consistency)
- Custom select implementations
### Examples
```tsx
// Basic select
<Select value={value} onValueChange={setValue}>
<SelectTrigger>
<SelectValue placeholder="Select an option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="option1">Option 1</SelectItem>
<SelectItem value="option2">Option 2</SelectItem>
<SelectItem value="option3">Option 3</SelectItem>
</SelectContent>
</Select>
```
---
## Dialog
**Location**: `@/components/ui/dialog`
**Import**: `import { Dialog } from '@/components/ui/dialog'`
### When to Use
**DO use Dialog component for:**
- Confirmation dialogs
- Alert dialogs
- Information dialogs
- Modal forms
### Variants
| Variant | Use Case |
|---------|----------|
| `default` | Standard dialog |
| `alert` | Error/warning messages (red icon) |
| `confirm` | Confirmation dialogs (cyan icon) |
| `info` | Information dialogs (cyan icon) |
### Examples
```tsx
// Confirmation dialog
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
title="Delete Track"
variant="alert"
onConfirm={handleDelete}
confirmLabel="Delete"
cancelLabel="Cancel"
>
<p>Are you sure you want to delete this track? This action cannot be undone.</p>
</Dialog>
```
---
## Alert
**Location**: `@/components/ui/alert`
**Import**: `import { Alert, AlertDescription } from '@/components/ui/alert'`
### When to Use
**DO use Alert component for:**
- Success messages
- Warning messages
- Error messages (non-critical)
- Information messages
### Examples
```tsx
// Success alert
<Alert variant="success">
<AlertDescription>Track uploaded successfully!</AlertDescription>
</Alert>
// Error alert
<Alert variant="error">
<AlertDescription>Failed to upload track. Please try again.</AlertDescription>
</Alert>
```
---
## Badge
**Location**: `@/components/ui/badge`
**Import**: `import { Badge } from '@/components/ui/badge'`
### When to Use
**DO use Badge component for:**
- Status indicators
- Tags
- Counts
- Labels
### Examples
```tsx
// Status badge
<Badge variant="success">Active</Badge>
<Badge variant="error">Inactive</Badge>
// Count badge
<Badge variant="secondary">42</Badge>
```
---
## Best Practices
### 1. Always Use Design System Components
- ✅ Use `Button` instead of `<button>`
- ✅ Use `Input` instead of `<input>`
- ✅ Use `Card` instead of custom card implementations
- ✅ Use `Select` instead of native `<select>`
### 2. Component Composition
- Compose components using sub-components (e.g., `CardHeader`, `CardContent`)
- Use className for custom styling when needed
- Don't override design system styles unnecessarily
### 3. Accessibility
- All components include proper ARIA attributes
- Focus states are handled automatically
- Keyboard navigation is supported
### 4. Consistency
- Use consistent variants across similar actions
- Follow the variant guidelines (default for primary, outline for secondary, ghost for tertiary)
- Use appropriate sizes (sm for compact, default for standard, lg for prominent)
### 5. Performance
- Components are optimized with React.forwardRef
- Use `asChild` prop when composing with other components (Button only)
### 6. Testing
- All components have test files
- Test components before using in production
- Follow existing test patterns
---
## Migration Guide
### Migrating from Custom Buttons
**Before:**
```tsx
<button className="px-4 py-2 bg-kodo-cyan text-white rounded">
Click me
</button>
```
**After:**
```tsx
<Button variant="default">Click me</Button>
```
### Migrating from Custom Cards
**Before:**
```tsx
<div className="rounded-lg border bg-kodo-ink p-4">
<h3>Title</h3>
<p>Content</p>
</div>
```
**After:**
```tsx
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
</CardHeader>
<CardContent>
<p>Content</p>
</CardContent>
</Card>
```
---
## Resources
- **Design System Colors**: See `apps/web/src/styles/COLOR_USAGE.md`
- **Component Tests**: See `apps/web/src/components/ui/*.test.tsx`
- **Component Source**: See `apps/web/src/components/ui/*.tsx`
---
## Questions?
If you're unsure which component to use:
1. Check this guide first
2. Look at similar components in the codebase
3. Review component test files for usage examples
4. When in doubt, use the most common variant (default for Button, standard for others)