Spaces:
Runtime error
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 backgroundSOLD_OUT- Gray backgroundDISCONTINUED- 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
- Project Overview - Architecture and features
- Source Tree - File locations
- Development Guide - Setup instructions