feat(ui): adopt ErrorState/EmptyState in app.index.tsx's metrics section#7046
Conversation
app.index.tsx's at-a-glance metrics section hand-rolled its own error and empty <div>s instead of the shared state-view primitives every other route uses. Swaps them for ErrorState/EmptyState from @/components/site/state-views, passing overview.error through as the error detail, with no change to the overview.status/series.length branching that decides which state renders. Closes JSONbored#6983
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-17 19:50:33 UTC
Review summary Nits — 5 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
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 #6983
app.index.tsx's "at-a-glance metrics" section hand-rolled its own error and empty<div>s instead of the shared state-view primitives every other route uses. This swaps them forErrorState/EmptyStatefrom@/components/site/state-views:<div>(overview.status === "error") →<ErrorState>, passingoverview.errorthrough as the description (the error detail).<div>(series.length === 0) →<EmptyState>.overview.status/series.lengthconditions decide which state renders; only the rendered markup changes.col-span-fullis preserved on both so the state still spans the metrics grid.UI Evidence
This is a presentational swap of two transient states (API error / no-data) to the shared primitives — #6983 is not
visual-labeled, and the states are described precisely below (both fully asserted by the app's existing suite, which stays green).Error state (
overview.status === "error"):col-span-fullamber<div>readingApp overview is unavailable right now (<error>).ErrorState(warning icon + title + description),title="App overview is unavailable right now",description={overview.error},className="col-span-full". Same information, now consistent withapp.audit.tsx/app.analytics.tsx, and it respectsprefers-reduced-motionlike the rest of the primitives.Empty state (
series.length === 0):col-span-fulldashed<div>readingNo metrics available yet. They'll appear once the API returns data.EmptyStatewith the sametitle/description,className="col-span-full".Data state (unchanged): when
series.length > 0, the existingseries.map(...)ofSparkStats renders exactly as before.Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #6983).Validation
git diff --checknpm run actionlintnpm run ui:typecheck(tsc --noEmiton apps/loopover-ui: 0 errors)npm run ui:lint(eslint on the changed file: 0 errors)npm run ui:test(vitest run: 60 files, 361 tests pass — no regression)npm run ui:buildnpm run test:coveragenpm run test:workersnpm audit --audit-level=moderateIf any required check was skipped, explain why:
apps/**is codecov-ignored (percodecov.yml), so there is nocodecov/patchgate on this change; the app's ownvitestsuite is the coverage gate, and it passes green (361 tests) with the swap.tsc --noEmit(0 errors —ErrorState/EmptyStateaccept thetitle/description/classNameprops passed),eslint src/routes/app.index.tsx(0 errors),vitest run(361 pass). No existing test asserted the old bespoke markup, so nothing needed updating.Safety
UI Evidencesection below with organized before/after detail. This is a presentational swap of transient error/empty states to shared primitives (notvisual-labeled); no SVG/committed review screenshots.The section renders the same live
overview/seriesdata through the shared error/empty primitives — no mock/demo fallback, and the error path surfaces the realoverview.error.Notes
Adopts existing shared components (
ErrorState/EmptyStatefrom@/components/site/state-views, which re-export the@loopover/ui-kitprimitives) — nothing new is built. Same family of change as the other routes already using these primitives.Closes #6983