feat: full shadcn/ui component system with consistent typography

New components:
- ui/button.tsx — Button with primary/accent/surface/ghost/destructive variants
- ui/input.tsx — Input + Textarea with focus ring and CSS var theming
- ui/label.tsx — Radix Label with peer-disabled support
- ui/separator.tsx — Radix Separator
- ui/tooltip.tsx — Radix Tooltip with themed content
- ui/dialog.tsx — Radix Dialog replacing custom modal implementations
- ui/table.tsx — Table/TableHeader/TableBody/TableRow/TableHead/TableCell
- ui/typography.tsx — PageTitle/SectionHeading/Body/Muted/Caption/MonoCaption

Wired throughout all components:
- ConfirmDialog + FormModal migrated to Radix Dialog (focus trap, Escape, ARIA)
- All raw <button> → Button, <input>/<textarea> → Input/Textarea
- All repeated text patterns → typography components
- All hardcoded hex/rgba strings → COLOR constants
This commit is contained in:
Offending Commit
2026-04-24 13:56:13 -05:00
parent 91c78915e5
commit 9a74182f97
24 changed files with 1387 additions and 652 deletions

View File

@@ -4,6 +4,8 @@ import { EmptyState } from "@/components/shared/EmptyState";
import { ErrorAlert } from "@/components/shared/ErrorAlert";
import { PageLoader } from "@/components/shared/LoadingSpinner";
import { Pagination } from "@/components/shared/Pagination";
import { PageTitle, MonoCaption } from "@/components/ui/typography";
import { COLOR } from "@/lib/constants";
import { Link, useNavigate, useParams } from "@tanstack/react-router";
import { type Variants, motion } from "framer-motion";
import { ArrowLeft, ChevronRight, CircleDot, Clock, MessageSquare } from "lucide-react";
@@ -44,25 +46,21 @@ export function SessionList() {
</Link>
<div className="flex items-center gap-2 mb-1">
<MessageSquare className="w-5 h-5" style={{ color: "#6366f1" }} strokeWidth={1.5} />
<h1 className="text-xl font-semibold tracking-tight" style={{ color: "#e4e4f0" }}>
Sessions
</h1>
<PageTitle>Sessions</PageTitle>
{total > 0 && (
<span
className="ml-auto text-xs font-mono px-2 py-0.5 rounded-full"
style={{
background: "rgba(99,102,241,0.1)",
color: "#818cf8",
border: "1px solid rgba(99,102,241,0.2)",
background: COLOR.accentSubtle,
color: COLOR.accentText,
border: `1px solid ${COLOR.accentBorder}`,
}}
>
{total}
</span>
)}
</div>
<p className="text-xs font-mono mt-0.5" style={{ color: "rgba(148,163,184,0.4)" }}>
{workspaceId}
</p>
<MonoCaption className="mt-0.5" as="p">{workspaceId}</MonoCaption>
</motion.div>
<ErrorAlert error={error instanceof Error ? error : null} />
@@ -116,11 +114,11 @@ export function SessionList() {
>
<CircleDot
className="w-3 h-3"
style={{ color: "#34d399" }}
style={{ color: COLOR.success }}
strokeWidth={2}
/>
</motion.div>
<span className="text-xs" style={{ color: "#34d399" }}>
<span className="text-xs" style={{ color: COLOR.success }}>
Active
</span>
</div>
@@ -140,17 +138,15 @@ export function SessionList() {
style={{ color: "rgba(148,163,184,0.3)" }}
strokeWidth={1.5}
/>
<p className="text-xs font-mono" style={{ color: "rgba(148,163,184,0.3)" }}>
{new Date(session.created_at).toLocaleString()}
</p>
<MonoCaption>{new Date(session.created_at).toLocaleString()}</MonoCaption>
</div>
)}
{(session.metadata as Record<string, string> | null)?.source && (
<span
className="text-xs font-mono px-1.5 py-0.5 rounded"
style={{
background: "rgba(99,102,241,0.08)",
border: "1px solid rgba(99,102,241,0.15)",
background: COLOR.accentDim,
border: `1px solid ${COLOR.accentBorderStrong}`,
color: "rgba(148,163,184,0.6)",
}}
>