From a6c2864b748e1036bae3b4807af0db131c17cb60 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Thu, 5 Feb 2026 09:01:22 +0100 Subject: [PATCH] feat(21-02): add skeleton loading states to initiative detail page Replace plain "Loading initiative..." and "Loading phases..." text with structured skeleton placeholders matching the page layout: header with back arrow/title/badge, two-column grid with phase accordions and sidebar panels. --- packages/web/src/routes/initiatives/$id.tsx | 31 ++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/web/src/routes/initiatives/$id.tsx b/packages/web/src/routes/initiatives/$id.tsx index 4e621c1..da79a26 100644 --- a/packages/web/src/routes/initiatives/$id.tsx +++ b/packages/web/src/routes/initiatives/$id.tsx @@ -2,6 +2,7 @@ import { useState, useCallback } from "react"; import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { AlertCircle } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { Skeleton } from "@/components/Skeleton"; import { trpc } from "@/lib/trpc"; import { InitiativeHeader } from "@/components/InitiativeHeader"; import { ProgressPanel } from "@/components/ProgressPanel"; @@ -313,8 +314,28 @@ function InitiativeDetailPage() { // Loading state if (initiativeQuery.isLoading) { return ( -
- Loading initiative... +
+ {/* Header skeleton */} +
+ + + +
+ + {/* Two-column grid skeleton */} +
+ {/* Left: phase accordion skeletons */} +
+ + +
+ + {/* Right: ProgressPanel + DecisionList skeletons */} +
+ + +
+
); } @@ -381,8 +402,10 @@ function InitiativeDetailPage() { {/* Phase loading */} {phasesQuery.isLoading && ( -
- Loading phases... +
+ {Array.from({ length: 3 }).map((_, i) => ( + + ))}
)}