Spaces:
Runtime error
Runtime error
docs: Introduce comprehensive technical documentation and update planning artifacts to reflect MVP completion and detailed FR implementation status.
d03d74d | # 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 | |