FormSkeleton — Settings
Three sections, four fields each. Mirrors the Settings VerticalTabs panel content shape: section title + sub-copy + label/input pairs.
Lightmax-w-3xl
Darkmax-w-3xl
DashboardSkeleton — PeopleDashboard, RoutesDashboard
Four-card metric row + chart placeholder. Same density as the real dashboard once data arrives. Linear/Stripe pattern.
Light~1280px
Dark~1280px
TableCard isLoading — Pay, Incident, Training
Was a generic grey pulse; now uses the same mint shimmer as everything else. Wired into Pay / Incident / Training so the value chip never flashes "0" before data lands.
Light3-card row
Timesheet hours
Route review hours
Gap in minutes
Dark3-card row
Timesheet hours
Route review hours
Gap in minutes
What ships in this MR
- FormSkeleton, DashboardSkeleton added as named exports of
src/components/skeleton/Skeleton.tsx; both use the new.skeleton-blockclass (alias to existing.table-skeleton-cellshimmer). - Existing primitives (SkeletonLine / SkeletonCircle / SkeletonBox / PageSkeleton) migrated from
animate-pulse bg-gray-*to.skeleton-block— single visual language across the codebase. - Settings uses
FormSkeletonon first-paint instead of branded md kangaroo. - PeopleDashboard, RoutesDashboard use
DashboardSkeletonon first-paint instead of branded md kangaroo. - TableCard isLoading rewritten to use
.skeleton-block;isLoading={isFetching}wired through Pay, Incident, Training so the value never flashes "0". - LiveMap map overlay bumped from md → lg kangaroo (map is the data render, the one place lg is right).
- route360 TrackPage in-button loader fixed from branded md → utility sm (per polish bar item 11: in-button = utility sm).
- route360/Dashboard.tsx not touched — its loaders are progressive-load section loaders, not page-level first-paint. Right call to leave alone.