From 00de7e46f14f0b17e69d88ef9ae0c3fd98fbeece Mon Sep 17 00:00:00 2001 From: Forgotten Date: Tue, 17 Feb 2026 20:07:54 -0600 Subject: [PATCH] Add DesignGuide page for component development reference Showcases all UI primitives (Button, Badge, Input, Textarea, Card, Dialog, Tooltip, Tabs, Skeleton, etc.) with Paperclip's dark theme. Accessible at /design-guide; not linked in the main sidebar. Co-Authored-By: Claude Sonnet 4.6 --- ui/src/pages/DesignGuide.tsx | 973 +++++++++++++++++++++++++++++++++++ 1 file changed, 973 insertions(+) create mode 100644 ui/src/pages/DesignGuide.tsx diff --git a/ui/src/pages/DesignGuide.tsx b/ui/src/pages/DesignGuide.tsx new file mode 100644 index 00000000..6322e73e --- /dev/null +++ b/ui/src/pages/DesignGuide.tsx @@ -0,0 +1,973 @@ +import { useState } from "react"; +import { + Bot, + CircleDot, + DollarSign, + Hexagon, + History, + Inbox, + LayoutDashboard, + ListTodo, + Mail, + Plus, + Search, + Settings, + Target, + Trash2, + Upload, + User, + Zap, +} from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Label } from "@/components/ui/label"; +import { Separator } from "@/components/ui/separator"; +import { Skeleton } from "@/components/ui/skeleton"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, + CardFooter, +} from "@/components/ui/card"; +import { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from "@/components/ui/dialog"; +import { + Tooltip, + TooltipTrigger, + TooltipContent, +} from "@/components/ui/tooltip"; +import { + Avatar, + AvatarFallback, + AvatarGroup, + AvatarGroupCount, +} from "@/components/ui/avatar"; +import { StatusBadge } from "@/components/StatusBadge"; +import { StatusIcon } from "@/components/StatusIcon"; +import { PriorityIcon } from "@/components/PriorityIcon"; +import { EntityRow } from "@/components/EntityRow"; +import { EmptyState } from "@/components/EmptyState"; +import { MetricCard } from "@/components/MetricCard"; +import { FilterBar, type FilterValue } from "@/components/FilterBar"; +import { InlineEditor } from "@/components/InlineEditor"; +import { PageSkeleton } from "@/components/PageSkeleton"; + +/* ------------------------------------------------------------------ */ +/* Section wrapper */ +/* ------------------------------------------------------------------ */ + +function Section({ title, children }: { title: string; children: React.ReactNode }) { + return ( +
+

+ {title} +

+ + {children} +
+ ); +} + +function SubSection({ title, children }: { title: string; children: React.ReactNode }) { + return ( +
+

{title}

+ {children} +
+ ); +} + +/* ------------------------------------------------------------------ */ +/* Color swatch */ +/* ------------------------------------------------------------------ */ + +function Swatch({ name, cssVar }: { name: string; cssVar: string }) { + return ( +
+
+
+

{cssVar}

+

{name}

+
+
+ ); +} + +/* ------------------------------------------------------------------ */ +/* Page */ +/* ------------------------------------------------------------------ */ + +export function DesignGuide() { + const [status, setStatus] = useState("todo"); + const [priority, setPriority] = useState("medium"); + const [inlineText, setInlineText] = useState("Click to edit this text"); + const [filters, setFilters] = useState([ + { key: "status", label: "Status", value: "Active" }, + { key: "priority", label: "Priority", value: "High" }, + ]); + + return ( +
+ {/* Page header */} +
+

Design Guide

+

+ Every component, style, and pattern used across Paperclip. +

+
+ + {/* ============================================================ */} + {/* COLORS */} + {/* ============================================================ */} +
+ +
+ + + + + + + + + + + + +
+
+ + +
+ + +
+
+ + +
+ + + + + +
+
+
+ + {/* ============================================================ */} + {/* TYPOGRAPHY */} + {/* ============================================================ */} +
+
+

Page Title — text-xl font-bold

+

Section Title — text-lg font-semibold

+

+ Section Heading — text-sm font-semibold uppercase tracking-wide +

+

Card Title — text-sm font-medium

+

Card Title Alt — text-sm font-semibold

+

Body text — text-sm

+

+ Muted description — text-sm text-muted-foreground +

+

+ Tiny label — text-xs text-muted-foreground +

+

+ Mono identifier — text-xs font-mono text-muted-foreground +

+

Large stat — text-2xl font-bold

+

Log/code text — font-mono text-xs

+
+
+ + {/* ============================================================ */} + {/* SPACING & RADIUS */} + {/* ============================================================ */} +
+
+ {[ + ["sm", "var(--radius-sm)"], + ["md", "var(--radius-md)"], + ["lg", "var(--radius-lg)"], + ["xl", "var(--radius-xl)"], + ["full", "9999px"], + ].map(([label, radius]) => ( +
+
+ {label} +
+ ))} +
+
+ + {/* ============================================================ */} + {/* BUTTONS */} + {/* ============================================================ */} +
+ +
+ + + + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+
+ + +
+ + +
+
+
+ + {/* ============================================================ */} + {/* BADGES */} + {/* ============================================================ */} +
+ +
+ Default + Secondary + Outline + Destructive + Ghost +
+
+
+ + {/* ============================================================ */} + {/* STATUS BADGES & ICONS */} + {/* ============================================================ */} +
+ +
+ {[ + "active", "running", "paused", "idle", "archived", "planned", + "achieved", "completed", "failed", "succeeded", "error", "backlog", + "todo", "in_progress", "in_review", "blocked", "done", + "cancelled", "pending", "approved", "rejected", + ].map((s) => ( + + ))} +
+
+ + +
+ {["backlog", "todo", "in_progress", "in_review", "done", "cancelled", "blocked"].map( + (s) => ( +
+ + {s} +
+ ) + )} +
+
+ + Click the icon to change status (current: {status}) +
+
+ + +
+ {["critical", "high", "medium", "low"].map((p) => ( +
+ + {p} +
+ ))} +
+
+ + Click the icon to change (current: {priority}) +
+
+ + +
+ {[ + ["running", "bg-cyan-400 animate-pulse"], + ["active", "bg-green-400"], + ["paused", "bg-yellow-400"], + ["error", "bg-red-400"], + ["offline", "bg-neutral-400"], + ].map(([label, color]) => ( +
+ + + + {label} +
+ ))} +
+
+ + +
+ {[ + ["timer", "bg-blue-900/50 text-blue-300"], + ["assignment", "bg-violet-900/50 text-violet-300"], + ["on_demand", "bg-cyan-900/50 text-cyan-300"], + ["webhook", "bg-neutral-800 text-neutral-400"], + ].map(([label, cls]) => ( + + {label} + + ))} +
+
+
+ + {/* ============================================================ */} + {/* FORM ELEMENTS */} + {/* ============================================================ */} +
+
+ + + + + + +