Files
ui-kit/showcase/showcase.tsx
T
Jason Stedwell 822d8e41e6
ci / build-and-design (push) Failing after 13s
visual upgrade
2026-07-23 04:23:19 -05:00

255 lines
12 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import * as React from "react";
import {
Badge,
Button,
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
Checkbox,
CommandPalette,
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EmptyState,
FeatureGrid,
FormField,
Hero,
Input,
Label,
Pagination,
Pricing,
Select,
Skeleton,
Spinner,
StatCard,
Switch,
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
Textarea,
Toaster,
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
AppShell,
useTheme,
} from "../src";
import {
BarChart3,
Blocks,
CheckCircle2,
Command,
CreditCard,
LayoutDashboard,
Moon,
MoreHorizontal,
Palette,
Plus,
Search,
Settings,
Sparkles,
Sun,
Users,
} from "lucide-react";
type Page = "overview" | "components" | "marketing";
function Section({
title,
description,
children,
}: {
title: string;
description: string;
children: React.ReactNode;
}) {
return (
<section className="space-y-4">
<div>
<h2 className="font-display text-xl font-semibold">{title}</h2>
<p className="mt-1 max-w-2xl text-sm text-muted">{description}</p>
</div>
{children}
</section>
);
}
function ThemeButton() {
const { resolvedTheme, toggleTheme } = useTheme();
return (
<Tooltip>
<TooltipTrigger asChild>
<Button type="button" variant="ghost" size="icon" onClick={toggleTheme} aria-label="Toggle color theme">
{resolvedTheme === "dark" ? <Sun /> : <Moon />}
</Button>
</TooltipTrigger>
<TooltipContent>Use {resolvedTheme === "dark" ? "light" : "dark"} mode</TooltipContent>
</Tooltip>
);
}
function Overview() {
return (
<div className="space-y-10">
<div>
<Badge variant="brand">Living design system</Badge>
<h1 className="mt-3 font-display text-3xl font-bold tracking-tight sm:text-4xl">Warm, clear, dependable interfaces.</h1>
<p className="mt-3 max-w-2xl text-muted">A single place to review brand tokens, responsive behavior, interaction states, and accessibility before changes reach consuming apps.</p>
</div>
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
<StatCard label="Components" animate={28} icon={<Blocks />} />
<StatCard label="Accessibility" value="AA" intent="success" sub="Contrast-gated themes" icon={<CheckCircle2 />} />
<StatCard label="Themes" value="3 modes" intent="brand" sub="Dark, light, and system" icon={<Palette />} />
<StatCard label="Build" value="Typed" intent="brand" sub="ESM and declarations" icon={<Sparkles />} />
</div>
<Section title="Operational surface" description="Representative dashboard density, controls, and data presentation.">
<Card>
<CardHeader className="flex-row items-start justify-between">
<div>
<CardTitle>Recent workspaces</CardTitle>
<CardDescription>Tables remain legible and horizontally scroll when space is constrained.</CardDescription>
</div>
<Button size="sm"><Plus />New workspace</Button>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow><TableHead>Name</TableHead><TableHead>Owner</TableHead><TableHead>Status</TableHead><TableHead className="text-right">Members</TableHead></TableRow>
</TableHeader>
<TableBody>
<TableRow><TableCell className="font-medium">Forge inventory</TableCell><TableCell>Jordan Lee</TableCell><TableCell><Badge variant="success">Healthy</Badge></TableCell><TableCell className="text-right">18</TableCell></TableRow>
<TableRow><TableCell className="font-medium">Field operations</TableCell><TableCell>Sam Rivera</TableCell><TableCell><Badge variant="warning">Review</Badge></TableCell><TableCell className="text-right">12</TableCell></TableRow>
<TableRow><TableCell className="font-medium">Quality portal</TableCell><TableCell>Alex Morgan</TableCell><TableCell><Badge>Draft</Badge></TableCell><TableCell className="text-right">7</TableCell></TableRow>
</TableBody>
</Table>
</CardContent>
</Card>
</Section>
</div>
);
}
function Components() {
const [notifications, setNotifications] = React.useState(true);
const [page, setPage] = React.useState(2);
return (
<div className="space-y-12">
<div>
<h1 className="font-display text-3xl font-bold tracking-tight">Components</h1>
<p className="mt-2 text-muted">Every core state in one executable review surface.</p>
</div>
<Section title="Actions and status" description="Variants share predictable sizing, focus, disabled, and semantic foreground behavior.">
<div className="flex flex-wrap gap-3">
<Button>Primary</Button><Button variant="secondary">Secondary</Button><Button variant="outline">Outline</Button><Button variant="ghost">Ghost</Button><Button variant="danger">Delete</Button><Button disabled>Disabled</Button><Spinner label="Saving…" />
</div>
<div className="flex flex-wrap gap-2">
<Badge variant="brand">Brand</Badge><Badge>Neutral</Badge><Badge variant="success">Success</Badge><Badge variant="warning">Warning</Badge><Badge variant="danger">Danger</Badge><Badge variant="outline">Outline</Badge>
</div>
</Section>
<Section title="Forms" description="Field-level descriptions and errors are automatically associated with controls.">
<Card className="max-w-2xl">
<CardContent className="grid gap-5 pt-5 sm:grid-cols-2">
<FormField label="Workspace name" description="Shown in the primary navigation."><Input placeholder="Forge inventory" /></FormField>
<FormField label="Region" required>
<Select defaultValue="" placeholder="Choose a region">
<option value="">Not assigned</option>
<optgroup label="Americas"><option value="us">United States</option><option value="ca">Canada</option></optgroup>
<optgroup label="Europe"><option value="uk">United Kingdom</option></optgroup>
</Select>
</FormField>
<FormField label="Summary" error="Add at least 20 characters" className="sm:col-span-2"><Textarea placeholder="What is this workspace for?" /></FormField>
<Label className="mb-0 flex items-center gap-2 text-sm text-text"><Checkbox defaultChecked />Email weekly digest</Label>
<Label className="mb-0 flex items-center justify-between gap-3 text-sm text-text">Notifications<Switch checked={notifications} onCheckedChange={setNotifications} /></Label>
</CardContent>
</Card>
</Section>
<Section title="Disclosure and navigation" description="Keyboard-friendly Radix foundations with branded surfaces.">
<div className="flex flex-wrap gap-3">
<Dialog>
<DialogTrigger asChild><Button variant="outline">Open dialog</Button></DialogTrigger>
<DialogContent><DialogHeader><DialogTitle>Invite collaborators</DialogTitle><DialogDescription>Send a secure invitation to this workspace.</DialogDescription></DialogHeader><FormField label="Email"><Input type="email" placeholder="name@example.com" /></FormField><Button className="mt-5 w-full">Send invitation</Button></DialogContent>
</Dialog>
<DropdownMenu>
<DropdownMenuTrigger asChild><Button variant="outline">More actions<MoreHorizontal /></Button></DropdownMenuTrigger>
<DropdownMenuContent><DropdownMenuItem>Duplicate</DropdownMenuItem><DropdownMenuItem>Archive</DropdownMenuItem><DropdownMenuItem className="text-danger">Delete</DropdownMenuItem></DropdownMenuContent>
</DropdownMenu>
</div>
<Tabs defaultValue="details" className="max-w-2xl">
<TabsList><TabsTrigger value="details">Details</TabsTrigger><TabsTrigger value="activity">Activity</TabsTrigger><TabsTrigger value="settings">Settings</TabsTrigger></TabsList>
<TabsContent value="details"><Card><CardContent className="pt-5 text-sm text-muted">Overview content with a calm, raised surface.</CardContent></Card></TabsContent>
<TabsContent value="activity"><EmptyState title="No activity yet" hint="Changes will appear here." /></TabsContent>
<TabsContent value="settings"><div className="space-y-2"><Skeleton className="h-10 w-full" /><Skeleton className="h-24 w-full" /></div></TabsContent>
</Tabs>
<Pagination page={page} pageCount={6} onPageChange={setPage} className="max-w-xl" />
</Section>
</div>
);
}
function Marketing() {
return (
<div className="-m-4 sm:-m-6">
<Hero eyebrow="Shared foundation" title="Ship tools that look designed." subtitle="Product UI first, with a confident editorial brand layer when the moment calls for it." primaryCta={{ label: "Get started", href: "#pricing" }} secondaryCta={{ label: "View components", href: "#components" }} />
<FeatureGrid heading="Built for real work" features={[
{ icon: <Command />, title: "Fast by default", description: "Command-first patterns and predictable controls keep operators moving." },
{ icon: <Palette />, title: "One visual language", description: "Generated tokens keep product and marketing surfaces in sync." },
{ icon: <CheckCircle2 />, title: "Guarded quality", description: "Contrast, interaction, and packaging checks run before release." },
]} />
<div id="pricing">
<Pricing heading="Simple plans" tiers={[
{ name: "Starter", price: "$0", period: "month", features: ["One workspace", "Core components"], cta: { label: "Start free" } },
{ name: "Team", price: "$24", period: "month", featured: true, description: "For active operators", features: ["Unlimited workspaces", "Priority support", "Advanced blocks"], cta: { label: "Choose Team" } },
{ name: "Custom", price: "Lets talk", features: ["Brand adaptation", "Migration support"], cta: { label: "Contact us" } },
]} />
</div>
</div>
);
}
export function Showcase() {
const [page, setPage] = React.useState<Page>("overview");
const nav = [
{ label: "Overview", icon: <LayoutDashboard />, active: page === "overview", onClick: () => setPage("overview") },
{ label: "Components", icon: <Blocks />, active: page === "components", onClick: () => setPage("components") },
{ label: "Marketing", icon: <CreditCard />, active: page === "marketing", onClick: () => setPage("marketing") },
];
return (
<TooltipProvider delayDuration={250}>
<AppShell
brand={<span className="flex items-center gap-2"><span className="size-2 rounded-full bg-brand shadow-glow" />UI Kit</span>}
nav={nav}
topbar={<><div className="flex min-w-0 items-center gap-2 text-sm text-muted"><Search className="size-4" /><span className="truncate">Review components, themes, and responsive states</span></div><div className="ml-auto flex items-center gap-1"><Badge variant="outline">v0.5 preview</Badge><ThemeButton /></div></>}
footer={<div className="flex items-center gap-2"><Settings className="size-4" />Design settings</div>}
>
{page === "overview" && <Overview />}
{page === "components" && <Components />}
{page === "marketing" && <Marketing />}
</AppShell>
<CommandPalette actions={[
{ id: "overview", label: "Open overview", group: "Navigate", icon: <BarChart3 />, onSelect: () => setPage("overview") },
{ id: "components", label: "Open components", group: "Navigate", icon: <Blocks />, onSelect: () => setPage("components") },
{ id: "marketing", label: "Open marketing blocks", group: "Navigate", icon: <Sparkles />, onSelect: () => setPage("marketing") },
{ id: "users", label: "Invite collaborator", group: "Actions", icon: <Users />, onSelect: () => undefined },
]} />
<Toaster />
</TooltipProvider>
);
}