Context
state-views.tsx:258-260's doc comment explains the loadingSkeleton prop exists specifically to avoid a layout jump when a list/table's content mounts after a generic spinner. apps/loopover-ui/src/routes/app.runs.tsx:251,612-620 passes a custom RunsListSkeleton and gets this benefit. Structurally similar list/table dashboards don't: components/site/dead-letter-queue-panel.tsx, components/site/app-panels/maintainer-panel.tsx (which drives ContributorQualityTable), and miner-panel.tsx all fall through to the generic centered spinner (LoadingState) instead.
Requirements
- Build a content-shaped skeleton for each of the 3 named components' actual table/list shape (following
RunsListSkeleton's approach: approximate the real layout's row/column structure so the transition from loading to loaded doesn't visibly jump), and pass it as loadingSkeleton to their StateBoundary.
- Do not change the generic
LoadingState component itself — it's still correct for boundaries that don't have a fixed content shape.
- This is a UI-only change under
apps/**.
Deliverables
Expected Outcome
Loading these 3 dashboards no longer produces a visible layout jump when data arrives, matching app.runs.tsx's existing UX.
Links & Resources
apps/loopover-ui/src/routes/app.runs.tsx:251,612-620 (RunsListSkeleton, the pattern to follow)
apps/loopover-ui/src/components/site/app-panels/state-views.tsx:258-260
components/site/dead-letter-queue-panel.tsx, components/site/app-panels/maintainer-panel.tsx, miner-panel.tsx
Context
state-views.tsx:258-260's doc comment explains theloadingSkeletonprop exists specifically to avoid a layout jump when a list/table's content mounts after a generic spinner.apps/loopover-ui/src/routes/app.runs.tsx:251,612-620passes a customRunsListSkeletonand gets this benefit. Structurally similar list/table dashboards don't:components/site/dead-letter-queue-panel.tsx,components/site/app-panels/maintainer-panel.tsx(which drivesContributorQualityTable), andminer-panel.tsxall fall through to the generic centered spinner (LoadingState) instead.Requirements
RunsListSkeleton's approach: approximate the real layout's row/column structure so the transition from loading to loaded doesn't visibly jump), and pass it asloadingSkeletonto theirStateBoundary.LoadingStatecomponent itself — it's still correct for boundaries that don't have a fixed content shape.apps/**.Deliverables
dead-letter-queue-panel.tsxuses a content-shaped loading skeleton.maintainer-panel.tsx(forContributorQualityTable) uses a content-shaped loading skeleton.miner-panel.tsxuses a content-shaped loading skeleton.Expected Outcome
Loading these 3 dashboards no longer produces a visible layout jump when data arrives, matching
app.runs.tsx's existing UX.Links & Resources
apps/loopover-ui/src/routes/app.runs.tsx:251,612-620(RunsListSkeleton, the pattern to follow)apps/loopover-ui/src/components/site/app-panels/state-views.tsx:258-260components/site/dead-letter-queue-panel.tsx,components/site/app-panels/maintainer-panel.tsx,miner-panel.tsx