Skip to content

feat(miner-ui): adopt StateBoundary + skeletons on the Overview route - #6576

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
dhgoal:feat/miner-ui-overview-redesign
Jul 16, 2026
Merged

feat(miner-ui): adopt StateBoundary + skeletons on the Overview route#6576
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
dhgoal:feat/miner-ui-overview-redesign

Conversation

@dhgoal

@dhgoal dhgoal commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #6509

  • The Overview route's three summary cards (Run activity, Portfolio queue, Claims) 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 route had no skeleton anywhere.
  • Adopts the shared StateBoundary + Skeleton primitives from @loopover/ui-kit — the same ones the main app's routes (app.analytics.tsx, app.operator.tsx) already use. Each card now wraps its Stats 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.
  • Behavior and data are unchanged: the same three read-only sources, the same Stats, the same oldest-queued CLI-parity minutes (fix(miner-ui): oldestQueuedAgeMs computed/validated but never displayed, breaking the stated CLI/web-UI shared-data-path contract #6185). Each card still degrades independently, and errors auto-recover on the next successful poll — so no manual retry action is wired (matching the existing poll-driven UX).

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:

  • Before: a single line Loading run state… / Loading the portfolio queue… / Loading the claim ledger… (flat text-muted-foreground text), replaced abruptly by content on first poll.
  • After: 2 / 4 / 2 shimmer rows (@loopover/ui-kit Skeleton, animate-pulse) laid out exactly like the card's Stat rows (a label-width bar + a value-width bar per row), inside a role="status" region labelled e.g. "Loading run activity". The card keeps its height, so no layout shift when data arrives. Respects prefers-reduced-motion (the ui-kit Skeleton/animation primitives already do).

Cards — error state:

  • Before: an inline role="alert" line Could not read run state.
  • After: the shared StateBoundary error 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. Still role="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

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves (e.g. Closes #123) — a linked open issue is required for every contributor PR.

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck (miner-ui tsc --noEmit: 0 errors on the touched files — see note)
  • npm run test:coverage
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint (eslint on the changed files: 0 errors)
  • npm run ui:typecheck
  • npm run ui:build (vitest build/transform of the route succeeds)
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • Ran this app's own gate: vitest run --coverage183 tests pass across 16 files, with coverage 87.8% statements / 86.7% branches / 81.1% functions / 89.8% lines, above vitest.config.ts's thresholds (85/85/75/85). The src/routes group is 97%+; the new StateBoundary/CardStatsSkeleton paths are exercised by the loading-skeleton test (role="status" per card), the error test (2 independent alerts), and the unchanged data tests.
  • npx tsc --noEmit on apps/loopover-miner-ui reports 0 errors across the touched files. (It surfaces one pre-existing error in vite-chat-api.ts, which this PR does not touch, only when packages/loopover-engine's dist is stale; a fresh engine build — which CI does — clears it.)
  • eslint on both changed files: 0 errors. prettier --check: clean.
  • Root-level suites (workers/mcp/openapi/audit) are untouched by an Overview-route-only change; leaving them to CI.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests.
  • API/OpenAPI/MCP behavior is updated and tested where needed.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks.
  • Visible UI changes include a UI Evidence section 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 not visual-labeled; the states are fully asserted by tests. No SVG/committed review screenshots.
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs.

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, Skeleton from @loopover/ui-kit) — nothing new is built. Establishes the pattern for the sibling route redesigns (#6510/#6511/#6512).

Closes #6509

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
@dhgoal
dhgoal requested a review from JSONbored as a code owner July 16, 2026 14:51
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 16, 2026
@loopover-orb

loopover-orb Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-16 14:57:48 UTC

2 files · 1 AI reviewer · no blockers · readiness 82/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This diff swaps a hand-rolled Fallback loading/error component for the shared StateBoundary + Skeleton primitives from @​loopover/ui-kit across the three Overview summary cards, matching conventions already used elsewhere (app.analytics.tsx, app.operator.tsx). The behavior is unchanged (same data sources, same Stats, same #6185 CLI-parity minutes calc), and tests were updated to assert the new role="status" skeleton and StateBoundary error copy instead of the old flat text. Row counts passed to CardStatsSkeleton (2/4/2) correctly mirror each card's actual Stat count, including the portfolio card's conditional 'Oldest queued' row.

Nits — 5 non-blocking
  • apps/loopover-miner-ui/src/routes/index.tsx:95 — the portfolio card's skeleton always renders 4 rows even though the real card can render only 3 Stats when oldestQueuedAgeMs is null, so the skeleton height won't always match final content; worth a comment or accepting the minor mismatch.
  • apps/loopover-miner-ui/src/routes/index.tsx:109 — the `60000` ms-to-minutes divisor is unrelated to this diff's scope but was flagged as a magic number; consider a named constant if touching this again.
  • The issue linkage brief notes Redesign: Overview route (index.tsx) — StateBoundary + skeletons + optional chart adoption #6509 also scoped 'optional chart adoption', which this PR doesn't include — worth confirming with the maintainer whether that's deferred or out of scope for this PR.
  • apps/loopover-miner-ui/src/routes/index.tsx — consider extracting the errorDescription strings ('The local run-state API didn't respond...') into a shared helper since the three cards repeat nearly identical copy with only the API name varying.
  • app.test.tsx — the new tests only check StateBoundary's rendered output for loading/error, not that isLoading/isError booleans are wired correctly for all three `null`/`ok:false`/`ok:true` states per card; consider a table-driven test to close that gap without much added code.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #6509
Related work ⚠️ 2 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 125 registered-repo PR(s), 72 merged, 36 issue(s).
Contributor context ✅ Confirmed Gittensor contributor dhgoal; Gittensor profile; 125 PR(s), 36 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Partially addressed
The PR correctly replaces the local Fallback helper with the shared StateBoundary/Skeleton primitives from @​loopover/ui-kit (satisfying the blocked-prerequisite constraint since it imports the real path), and includes per-card skeletons with tests, but it does not implement the Portfolio queue card's status-breakdown chart via @​loopover/ui-kit/components/chart.tsx that the issue explicitly require

Review context
  • Author: dhgoal
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 125 PR(s), 36 issue(s).
  • Related work: Titles/paths share 8 meaningful terms. (issue #6509, issue #6510)
  • Related work: Titles/paths share 8 meaningful terms. (issue #6509, issue #6512)
Contributor next steps
  • Start here: Review top overlaps.
  • Then work through the remaining 2 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask 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.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before /
before /
after /
after /
/ mobile before / (mobile)
before / (mobile)
after / (mobile)
after / (mobile)

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.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit ed8aad0 into JSONbored:main Jul 16, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redesign: Overview route (index.tsx) — StateBoundary + skeletons + optional chart adoption

1 participant