refresh()} />
```
---
### ThemeProvider
**File**: `components/theme-provider.tsx`
**Purpose**: Wraps app with next-themes provider.
**Usage** (in layout):
```tsx
{children}
```
---
## 4. UI Components
All shadcn/ui components are available in `components/ui/`. Key components:
### Layout Components
- `Card`, `CardHeader`, `CardTitle`, `CardContent`, `CardFooter`
- `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`
- `Sheet`, `SheetTrigger`, `SheetContent`
- `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`
- `Table`, `TableHeader`, `TableRow`, `TableCell`
### Form Components
- `Button` - Primary actions
- `Input` - Text input
- `Textarea` - Multi-line input
- `Select`, `SelectTrigger`, `SelectContent`, `SelectItem`
- `Checkbox` - Boolean input
- `Switch` - Toggle input
- `Label` - Form labels
### Feedback Components
- `Badge` - Status indicators
- `Alert`, `AlertTitle`, `AlertDescription`
- `Spinner` - Loading indicator
- `Skeleton` - Loading placeholder
- `Toast`, `Toaster` - Notifications
### Navigation Components
- `Breadcrumb`, `BreadcrumbItem`, `BreadcrumbLink`
- `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent`
- `NavigationMenu`
---
## 5. Component Patterns
### Server/Client Split
```typescript
// page.tsx (Server Component)
export default async function FeaturePage() {
const supabase = await createClient()
const { data } = await supabase.from('table').select('*')
return
}
// feature-client.tsx (Client Component)
'use client'
export function FeatureClient({ data }: { data: Item[] }) {
const [items, setItems] = useState(data)
// Interactive UI
}
```
### Modal Pattern
```tsx
const [showModal, setShowModal] = useState(false)
const [form, setForm] = useState({ field: '' })
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
async function handleSubmit(e: React.FormEvent) {
e.preventDefault()
setLoading(true)
setError('')
const result = await serverAction(form)
if (result.error) {
setError(result.error)
setLoading(false)
return
}
// Update local state
setShowModal(false)
setForm({ field: '' })
setLoading(false)
}
return (
<>
{showModal && (
)}
>
)
```
### Optimistic Update Pattern
```tsx
async function handleAction(id: string) {
// Optimistically update UI
setItems(prev => prev.map(item =>
item.id === id ? { ...item, status: 'updated' } : item
))
// Call server
const result = await serverAction(id)
if (result.error) {
// Revert on error
setItems(prev => prev.map(item =>
item.id === id ? { ...item, status: 'original' } : item
))
}
}
```
### Tab Pattern
```tsx
const [activeTab, setActiveTab] = useState<'tab1' | 'tab2'>('tab1')
const tabData = {
tab1: items.filter(i => i.type === 'type1'),
tab2: items.filter(i => i.type === 'type2'),
}
return (
<>
{(['tab1', 'tab2'] as const).map(tab => (
))}
{tabData[activeTab].map(item => (
{/* Render item */}
))}
>
)
```
### Filter Pattern
```tsx
const [search, setSearch] = useState('')
const [filter, setFilter] = useState('')
const filtered = items.filter(item => {
const matchesSearch = !search ||
item.name.toLowerCase().includes(search.toLowerCase())
const matchesFilter = !filter || item.type === filter
return matchesSearch && matchesFilter
})
return (
<>
setSearch(e.target.value)}
placeholder="Search..."
/>
{filtered.map(item => (
{/* Render */}
))}
>
)
```
---
## 6. Styling Patterns
### Page Header
```tsx
```
### Tab Bar
```tsx
{tabs.map(tab => (
))}
```
### Card List
```tsx
{items.map(item => (
{/* Item content */}
))}
```
### Status Badge
```tsx
{status.toUpperCase()}
```
### Monospace Label
```tsx
SECTION LABEL
```