feat(miner-ui): adopt StateBoundary + skeletons on the Overview route - #6576
Conversation
The Overview route's three summary cards each rendered their loading/error surface with a hand-rolled Fallback helper -- a flat gray "Loading …" sentence and an inline error line, re-rendered every 10s poll. This adopts the shared @loopover/ui-kit primitives the main app's routes already use: each card wraps its Stats in <StateBoundary> with a content-shaped <Skeleton> placeholder that mirrors the card's Stat rows, so the layout no longer shifts when data arrives and the loading state reads as a live shimmer instead of static text. Error surfaces now use StateBoundary's shared alert; each card still degrades independently, and errors auto-recover on the next successful poll (no manual retry wired, matching the existing poll-driven UX). Behavior/data unchanged: same three read-only sources, same Stats, same oldest-queued CLI-parity minutes (JSONbored#6185). Updates the loading test to assert the per-card role=status skeleton and strengthens the error test to assert the shared StateBoundary copy. Closes JSONbored#6509
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-16 14:57:48 UTC
Review summary Nits — 5 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionPartially addressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. Visual preview
Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|

Summary
Closes #6509
Fallbackhelper — a flat gray "Loading …" sentence and an inline error line, re-rendered every 10s poll. This route had no skeleton anywhere.StateBoundary+Skeletonprimitives from@loopover/ui-kit— the same ones the main app's routes (app.analytics.tsx,app.operator.tsx) already use. Each card now wraps itsStats in<StateBoundary>with a content-shaped skeleton that mirrors the card's Stat rows, so the layout no longer shifts when data arrives and the loading state reads as a live shimmer rather than static text. Error surfaces use StateBoundary's shared alert.UI Evidence
This change is to the loading and error placeholder states (transient, poll-driven), not a static layout redesign — so the "visible" delta is best described precisely and is fully asserted by the tests below (#6509 is not
visual-labeled).Run activity / Portfolio queue / Claims cards — loading state:
Loading run state…/Loading the portfolio queue…/Loading the claim ledger…(flattext-muted-foregroundtext), replaced abruptly by content on first poll.@loopover/ui-kitSkeleton,animate-pulse) laid out exactly like the card'sStatrows (a label-width bar + a value-width bar per row), inside arole="status"region labelled e.g. "Loading run activity". The card keeps its height, so no layout shift when data arrives. Respectsprefers-reduced-motion(the ui-kit Skeleton/animation primitives already do).Cards — error state:
role="alert"lineCould not read run state.StateBoundaryerror surface (ErrorState) with per-card copy ("Couldn't read run state", "…the portfolio queue", "…the claim ledger") and a warning icon, consistent with the rest of the app. Stillrole="alert"; each card errors independently while the others render.Data state (unchanged): identical Stats and values; verified by the pre-existing "summarizes … from live data" and "#6185 oldest-queued minutes" tests, which pass unmodified.
Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #123) — a linked open issue is required for every contributor PR.Validation
git diff --checknpm run actionlintnpm run typecheck(miner-uitsc --noEmit: 0 errors on the touched files — see note)npm run test:coveragenpm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lint(eslint on the changed files: 0 errors)npm run ui:typechecknpm run ui:build(vitest build/transform of the route succeeds)npm audit --audit-level=moderateIf any required check was skipped, explain why:
vitest run --coverage— 183 tests pass across 16 files, with coverage 87.8% statements / 86.7% branches / 81.1% functions / 89.8% lines, abovevitest.config.ts's thresholds (85/85/75/85). Thesrc/routesgroup is 97%+; the newStateBoundary/CardStatsSkeletonpaths are exercised by the loading-skeleton test (role="status" per card), the error test (2 independent alerts), and the unchanged data tests.npx tsc --noEmitonapps/loopover-miner-uireports 0 errors across the touched files. (It surfaces one pre-existing error invite-chat-api.ts, which this PR does not touch, only whenpackages/loopover-engine'sdistis stale; a fresh engine build — which CI does — clears it.)eslinton both changed files: 0 errors.prettier --check: clean.Safety
UI Evidencesection below with organized before/after detail. This change is to transient loading/error states (not a static visual), and Redesign: Overview route (index.tsx) — StateBoundary + skeletons + optional chart adoption #6509 is notvisual-labeled; the states are fully asserted by tests. No SVG/committed review screenshots.Read-only Overview route: no auth/API/data-source change. The cards render live local API data with real loading/error/empty states via the shared
StateBoundary— no mock/demo fallback.Notes
Adopts existing shared components (
StateBoundary,Skeletonfrom@loopover/ui-kit) — nothing new is built. Establishes the pattern for the sibling route redesigns (#6510/#6511/#6512).Closes #6509