From cc60198578980d76375d8dcdf512731cde73d78c Mon Sep 17 00:00:00 2001 From: bokiko Date: Wed, 18 Mar 2026 12:21:51 +0000 Subject: [PATCH 1/2] feat(ui): replace spinner with skeleton loading screen on dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard previously showed a bare spinner + "Loading results..." text while waiting for the /api/results fetch. This gave no visual hint of page structure, causing layout shift when content arrived. Replaced with a full DashboardSkeleton component that mirrors the real layout: - Four stat cards (icon, value, sub-label placeholders) - Two chart panels with proportional bar columns - Recent Results table with six skeleton rows Uses the existing .skeleton shimmer CSS class (globals.css) — no new dependencies. The skeleton renders immediately on mount so the page always has visible content during the loading state. Also wires aria-busy='true' and aria-label on the skeleton root so screen readers know data is loading. Files: web/src/components/DashboardSkeleton.tsx (new), web/src/app/dashboard/page.tsx --- web/src/app/dashboard/page.tsx | 6 +- web/src/components/DashboardSkeleton.tsx | 121 +++++++++++++++++++++++ 2 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 web/src/components/DashboardSkeleton.tsx diff --git a/web/src/app/dashboard/page.tsx b/web/src/app/dashboard/page.tsx index deff416..5f1ba6c 100644 --- a/web/src/app/dashboard/page.tsx +++ b/web/src/app/dashboard/page.tsx @@ -14,6 +14,7 @@ import { } from "lucide-react"; import { Navbar } from "@/components/Navbar"; import { Footer } from "@/components/Footer"; +import { DashboardSkeleton } from "@/components/DashboardSkeleton"; import { LineChart, Line, @@ -181,10 +182,7 @@ export default function DashboardPage() { {loading ? ( -
-
-

Loading results...

-
+ ) : error ? (
diff --git a/web/src/components/DashboardSkeleton.tsx b/web/src/components/DashboardSkeleton.tsx new file mode 100644 index 0000000..cf23217 --- /dev/null +++ b/web/src/components/DashboardSkeleton.tsx @@ -0,0 +1,121 @@ +/** + * DashboardSkeleton — shimmer placeholders that mirror the real dashboard layout. + * + * Renders four stat cards, two chart panels, and a results table skeleton so the + * page feels instantly populated while data is in-flight. Uses a CSS animation + * defined in globals.css (shimmer keyframes) to avoid a runtime dependency. + */ + +function SkeletonBlock({ className = "" }: { className?: string }) { + return ( +