1.7 KiB
1.7 KiB
Plan 21-02 Summary: Skeleton Loading States
Result: COMPLETE
Duration: ~3 min Commits: 2
What was done
-
Created reusable Skeleton component (
packages/web/src/components/Skeleton.tsx)- Simple animated placeholder:
animate-pulse rounded-md bg-muted - Accepts
classNameprop merged viacn()for caller-controlled sizing - Named export for consistency with other components
- Simple animated placeholder:
-
Dashboard skeleton loading (
packages/web/src/components/InitiativeList.tsx)- Replaced "Loading initiatives..." text with 3 skeleton cards
- Each card matches InitiativeCard layout: title bar, status badge, progress bar, phase count
-
Inbox skeleton loading (
packages/web/src/routes/inbox.tsx)- Replaced "Loading inbox..." text with skeleton header + 4 skeleton message rows
- Each row matches MessageCard layout: status circle, name, preview text, timestamp
-
Detail page skeleton loading (
packages/web/src/routes/initiatives/$id.tsx)- Initiative loading: header skeleton (back arrow, title, badge) + two-column grid (phase accordions, sidebar panels)
- Phase loading: 3 skeleton accordion bars replacing "Loading phases..." text
Decisions
- 21-02: Skeleton component in components/ (not ui/) — it's app-specific, not a shadcn primitive
- 21-02: Inbox skeleton lives in inbox.tsx route (not InboxList component) since InboxList receives pre-loaded data
Verification
npx tsc --noEmit -p packages/web/tsconfig.app.json— passes (own files clean)npm run --workspace=packages/web build— succeeds- No "Loading..." plain text remains in loading paths
- Skeleton component exported and used consistently across all three screens