vault-video-processor / docs /ui-components.md
dvijaykrishnan's picture
docs: Introduce comprehensive technical documentation and update planning artifacts to reflect MVP completion and detailed FR implementation status.
d03d74d
|
Raw
History Blame Contribute Delete
12.4 kB
# Vault - UI Components
**Generated:** 2026-02-11
**Framework:** React 19 + shadcn/ui
**Styling:** Tailwind CSS 4
---
## Design System
### Theme Configuration
**Dark Theme (Default)**
| Token | Value | Usage |
|-------|-------|-------|
| `--background` | `#0A0B14` | Page backgrounds |
| `--foreground` | `#FFFFFF` | Primary text |
| `--primary` | `#4169FF` | Primary actions |
| `--muted` | `#1A1B2E` | Secondary backgrounds |
| `--border` | `#2A2B3E` | Borders, dividers |
### Breakpoints
| Breakpoint | Width | Target |
|------------|-------|--------|
| `sm` | 375px | Mobile (iOS Safari) |
| `md` | 768px | Tablet |
| `lg` | 1200px | Desktop |
### Glassmorphism Pattern
```css
.glass {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
```
---
## Shared UI Components
Located in [`src/components/ui/`](../src/components/ui/). These are shadcn/ui components with minimal customization.
### Layout Components
#### `Card`
Container for grouped content.
```tsx
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@/components/ui/card';
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Content</CardContent>
<CardFooter>Footer</CardFooter>
</Card>
```
#### `Badge`
Status indicators and labels.
```tsx
import { Badge } from '@/components/ui/badge';
<Badge variant="default">Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
<Badge variant="outline">Outline</Badge>
```
**Custom Variants:**
- `IN_STOCK` - Green background
- `SOLD_OUT` - Gray background
- `DISCONTINUED` - Blue background
### Form Components
#### `Button`
Primary interactive element.
```tsx
import { Button } from '@/components/ui/button';
<Button variant="default">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
```
#### `Input`
Text input field.
```tsx
import { Input } from '@/components/ui/input';
<Input type="text" placeholder="Enter text" />
```
#### `Textarea`
Multi-line text input.
```tsx
import { Textarea } from '@/components/ui/textarea';
<Textarea placeholder="Enter description" />
```
#### `Select`
Dropdown selection.
```tsx
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
<Select>
<SelectTrigger>
<SelectValue placeholder="Select option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Option 1</SelectItem>
<SelectItem value="2">Option 2</SelectItem>
</SelectContent>
</Select>
```
#### `Checkbox`
Boolean input.
```tsx
import { Checkbox } from '@/components/ui/checkbox';
<Checkbox id="terms" />
```
### Feedback Components
#### `Dialog`
Modal overlay.
```tsx
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Description</DialogDescription>
</DialogHeader>
{/* Content */}
</DialogContent>
</Dialog>
```
#### `AlertDialog`
Confirmation dialog.
```tsx
import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from '@/components/ui/alert-dialog';
<AlertDialog>
<AlertDialogTrigger>Delete</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
<AlertDialogDescription>This action cannot be undone.</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
```
#### `Sonner` (Toast)
Toast notifications.
```tsx
import { toast } from 'sonner';
toast.success('Success message');
toast.error('Error message');
toast.info('Info message');
```
### Navigation Components
#### `Tabs`
Tabbed navigation.
```tsx
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
<Tabs defaultValue="tab1">
<TabsList>
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
</TabsList>
<TabsContent value="tab1">Content 1</TabsContent>
<TabsContent value="tab2">Content 2</TabsContent>
</Tabs>
```
#### `DropdownMenu`
Dropdown navigation.
```tsx
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from '@/components/ui/dropdown-menu';
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Item 1</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>Item 2</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
```
### Data Display Components
#### `Avatar`
User avatar display.
```tsx
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
<Avatar>
<AvatarImage src="/avatar.png" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
```
#### `Skeleton`
Loading placeholder.
```tsx
import { Skeleton } from '@/components/ui/skeleton';
<Skeleton className="h-4 w-[250px]" />
```
---
## Feature Components
### Vault Components
Located in [`src/features/vault/components/`](../src/features/vault/components/).
#### `VaultGrid`
Main product grid display.
**File:** [`vault-grid.tsx`](../src/features/vault/components/vault-grid.tsx)
**Props:**
```typescript
interface VaultGridProps {
vault: CreatorVault;
products?: ProductCard[];
editUrl?: string;
hideVideos?: boolean;
}
```
**Features:**
- Client-side category filtering
- Responsive grid layout
- Empty state handling
- Video/product toggle
#### `ProductCard`
Individual product display.
**File:** [`product-card.tsx`](../src/features/vault/components/product-card.tsx)
**Props:**
```typescript
interface ProductCardProps {
id: string;
objectName: string;
category: string;
thumbnailUrl?: string;
frameTimestamp: number;
marketplaceMatches: MarketplaceMatch[];
videoId: string;
creatorId: string;
isAdmin?: boolean;
onRefresh?: () => void;
}
```
**Features:**
- Availability status badges
- Affiliate link redirect
- "I want this" interest capture
- FTC disclosure display
- Admin quick actions
#### `CategoryFilter`
Category tab navigation.
**File:** [`category-filter.tsx`](../src/features/vault/components/category-filter.tsx)
**Features:**
- URL parameter sync
- "All Items" default
- Dynamic category list
#### `SearchBar`
Product search input.
**File:** [`search-bar.tsx`](../src/features/vault/components/search-bar.tsx)
**Features:**
- Debounced search
- Loading state
- Results dropdown
#### `VideoCard`
Video thumbnail display.
**File:** [`video-card.tsx`](../src/features/vault/components/video-card.tsx)
**Features:**
- Play button overlay
- View count display
- Product count badge
### Moderation Components
Located in [`src/features/moderation/components/`](../src/features/moderation/components/).
#### `ModerationQueue`
Creator moderation interface.
**File:** [`moderation-queue.tsx`](../src/features/moderation/components/moderation-queue.tsx)
**Props:**
```typescript
interface ModerationQueueProps {
initialDetections: Detection[];
userId: string;
videos: { id: string; title: string }[];
stats: { pending: number; approved: number; rejected: number };
initialStatus?: 'PENDING' | 'APPROVED' | 'REJECTED';
}
```
**Features:**
- Status filtering
- Confidence filtering
- Video filtering
- Link status filtering
- Bulk selection
- Bulk approve/reject
- Click/interest sorting
#### `EditDetectionDialog`
Edit detection details.
**File:** [`edit-detection-dialog.tsx`](../src/features/moderation/components/edit-detection-dialog.tsx)
**Features:**
- Edit object name
- Change category
- Update thumbnail URL
- Add/edit marketplace links
#### `AddProductDialog`
Manually add product to video.
**File:** [`add-product-dialog.tsx`](../src/features/moderation/components/add-product-dialog.tsx)
**Features:**
- Object name input
- Category selection
- Timestamp input
- Marketplace link addition
#### `AdminModerationQueue`
Admin moderation interface.
**File:** [`admin-moderation-queue.tsx`](../src/features/moderation/components/admin-moderation-queue.tsx)
**Features:**
- High-ambiguity filtering
- Admin correction modal
- Mark incorrect with reason
- AI training flag
### Interest Components
Located in [`src/features/interest/components/`](../src/features/interest/components/).
#### `InterestCaptureModal`
"I want this" email capture.
**File:** [`interest-capture-modal.tsx`](../src/features/interest/components/interest-capture-modal.tsx)
**Props:**
```typescript
interface InterestCaptureModalProps {
isOpen: boolean;
onClose: () => void;
marketplaceMatchId?: string;
detectedObjectId?: string;
productName: string;
videoId?: string;
creatorId?: string;
}
```
**Features:**
- Email input
- GDPR consent checkbox
- Duplicate detection
- Success state
- Affiliate link submission option
### Analytics Components
Located in [`src/features/analytics/components/`](../src/features/analytics/components/).
#### `KeyMetricsRow`
Dashboard metrics display.
**File:** [`key-metrics-row.tsx`](../src/features/analytics/components/key-metrics-row.tsx)
**Props:**
```typescript
interface KeyMetricsRowProps {
stats?: {
totalClicks: number;
totalPledges: number;
totalRequests: number;
monetizedCount: number;
};
}
```
**Metrics:**
- Total Clicks
- Interest Pledges
- Product Requests
- Monetized Videos
### Auth Components
Located in [`src/components/auth/`](../src/components/auth/).
#### `UserNav`
User avatar dropdown.
**File:** [`user-nav.tsx`](../src/components/auth/user-nav.tsx)
**Features:**
- Avatar display
- Name display
- Dashboard link
- Sign out action
#### `SignInForm`
Login form.
**File:** [`sign-in-form.tsx`](../src/components/auth/sign-in-form.tsx)
**Features:**
- Google OAuth button
- Redirect after login
#### `SignUpForm`
Registration form.
**File:** [`sign-up-form.tsx`](../src/components/auth/sign-up-form.tsx)
**Features:**
- Google OAuth button
- Terms acceptance
---
## Common Patterns
### Loading States
```tsx
import { Skeleton } from '@/components/ui/skeleton';
// Card skeleton
<Card>
<CardHeader>
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-3 w-1/2" />
</CardHeader>
<CardContent>
<Skeleton className="h-32 w-full" />
</CardContent>
</Card>
// Grid skeleton
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{Array.from({ length: 8 }).map((_, i) => (
<ProductCardSkeleton key={i} />
))}
</div>
```
### Error Boundaries
```tsx
// In page component
if (!vault) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h2 className="text-2xl font-bold">Unable to load vault</h2>
<p className="text-muted-foreground">Please try again later.</p>
</div>
</div>
);
}
```
### Optimistic Updates
```tsx
const [isPending, startTransition] = useTransition();
const handleApprove = () => {
startTransition(async () => {
const result = await approveDetection(detectionId);
if (result.success) {
toast.success('Detection approved');
// Update local state optimistically
setDetections(prev => prev.filter(d => d.id !== detectionId));
} else {
toast.error(result.error);
}
});
};
```
### Responsive Design
```tsx
// Mobile-first responsive classes
<div className="
grid
grid-cols-1
sm:grid-cols-2
md:grid-cols-3
lg:grid-cols-4
gap-4
">
{products.map(product => (
<ProductCard key={product.id} {...product} />
))}
</div>
```
---
## Related Documentation
- [Project Overview](./project-overview.md) - Architecture and features
- [Source Tree](./source-tree.md) - File locations
- [Development Guide](./development-guide.md) - Setup instructions