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

.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/. These are shadcn/ui components with minimal customization.

Layout Components

Card

Container for grouped content.

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.

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.

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.

import { Input } from '@/components/ui/input';

<Input type="text" placeholder="Enter text" />

Textarea

Multi-line text input.

import { Textarea } from '@/components/ui/textarea';

<Textarea placeholder="Enter description" />

Select

Dropdown selection.

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.

import { Checkbox } from '@/components/ui/checkbox';

<Checkbox id="terms" />

Feedback Components

Dialog

Modal overlay.

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.

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.

import { toast } from 'sonner';

toast.success('Success message');
toast.error('Error message');
toast.info('Info message');

Navigation Components

Tabs

Tabbed navigation.

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.

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.

import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';

<Avatar>
  <AvatarImage src="/avatar.png" />
  <AvatarFallback>JD</AvatarFallback>
</Avatar>

Skeleton

Loading placeholder.

import { Skeleton } from '@/components/ui/skeleton';

<Skeleton className="h-4 w-[250px]" />

Feature Components

Vault Components

Located in src/features/vault/components/.

VaultGrid

Main product grid display.

File: vault-grid.tsx

Props:

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

Props:

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

Features:

  • URL parameter sync
  • "All Items" default
  • Dynamic category list

SearchBar

Product search input.

File: search-bar.tsx

Features:

  • Debounced search
  • Loading state
  • Results dropdown

VideoCard

Video thumbnail display.

File: video-card.tsx

Features:

  • Play button overlay
  • View count display
  • Product count badge

Moderation Components

Located in src/features/moderation/components/.

ModerationQueue

Creator moderation interface.

File: moderation-queue.tsx

Props:

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

Features:

  • Edit object name
  • Change category
  • Update thumbnail URL
  • Add/edit marketplace links

AddProductDialog

Manually add product to video.

File: add-product-dialog.tsx

Features:

  • Object name input
  • Category selection
  • Timestamp input
  • Marketplace link addition

AdminModerationQueue

Admin moderation interface.

File: 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/.

InterestCaptureModal

"I want this" email capture.

File: interest-capture-modal.tsx

Props:

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/.

KeyMetricsRow

Dashboard metrics display.

File: key-metrics-row.tsx

Props:

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/.

UserNav

User avatar dropdown.

File: user-nav.tsx

Features:

  • Avatar display
  • Name display
  • Dashboard link
  • Sign out action

SignInForm

Login form.

File: sign-in-form.tsx

Features:

  • Google OAuth button
  • Redirect after login

SignUpForm

Registration form.

File: sign-up-form.tsx

Features:

  • Google OAuth button
  • Terms acceptance

Common Patterns

Loading States

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

// 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

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

// 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