ui: the window belongs to the miner page, not just the standings
All checks were successful
deploy / build (push) Successful in 1m14s
deploy / deploy-api (push) Has been skipped
deploy / deploy-web (push) Successful in 6s

Choosing a window on a miner's page navigated back to the standings. Not a
mis-wired link: there was no URL for "this miner, over a day", so the only thing
the control could do was go somewhere that had one.

So the miner route carries it: `/quantus/miner/0x…/day`. That is the right place
for it regardless — a miner's rank and hashrate are *of* a window, and a link
sent without one shows the recipient something other than what the sender was
looking at. In the path rather than a query string, so it reads the way the
standings' own window already does. The bare `/quantus/miner/0x…` still resolves,
at the default window, so existing links keep working.

And the control now appears only where it changes something: the standings, and
a miner's page, which is one row of those same standings. A block happened once,
a balance has no span, a runtime is not a rate, and the three indexes are not
ranked — on all of those it was a live control that did nothing, which teaches a
reader to distrust it on the two pages where it works.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
This commit is contained in:
2026-09-10 06:23:38 +03:00
parent f9ea292a70
commit 93358dd920
3 changed files with 54 additions and 18 deletions

View File

@@ -305,6 +305,15 @@ Route segments are named — `/quantus/block/13160` rather than
two kinds of thing can look alike, and an SS58 address is arbitrary base58 with
no rule keeping it clear of a window name forever.
A miner's page carries the window too: `/quantus/miner/0x…/day`. Its rank and
hashrate are *of* a window, so a link without one means something different from
what the sender was looking at — and until it was in the path, changing the
window on a miner's page could only navigate back to the standings, because
there was no URL for "this miner, over a day". The window control appears on
exactly the two pages where it changes something, the standings and a miner;
a block happened once and a balance has no span, and a control that does nothing
where it sits teaches a reader to distrust it everywhere else.
Everything navigable is an `<a>`, including the chain chips and the window
control. That is what "real URLs" has to mean in practice: middle-click opens
the 24-hour view of another chain in a tab, right-click copies a link to a

View File

@@ -53,6 +53,11 @@ export default function App() {
}
}, [route.chain, route.window, fallbackChain, navigate])
// The standings and a miner's page, which is one row of them. Everything
// else is about a thing that happened once.
const windowApplies =
route.index === null && route.block === null && route.account === null && route.runtime === null
// Normalise a path that resolves to the standings but is not spelled like
// them: `/quantus`, `/quantus/miner` (the standings *are* the miner index),
// and anything unrecognised, which `parse` degrades to the front page rather
@@ -109,21 +114,29 @@ export default function App() {
</div>
<div className="masthead-right">
{/* Links, not buttons: a window is part of the address, so "the
last 24 hours on Quantus" is a thing to send someone rather than
a control state that a shared link would drop. */}
<nav className="segmented" aria-label="Leaderboard window">
{WINDOWS.map((w) => (
<Link
key={w.id}
to={href({ chain, window: w.id })}
aria-current={w.id === route.window ? 'page' : undefined}
title={`${w.blocks.toLocaleString('en-US')} blocks — ${windowSpan(w.blocks, interval)}`}
>
{w.label}
</Link>
))}
</nav>
{/* Only where a window means something. It sets the span the ranks
are computed over, so it belongs on the standings and on a
miner's page — which is one row of those same standings. A block,
an account, a runtime and the three indexes have no window: a
block happened once, a balance has no span, and a control that
does nothing where it sits teaches a reader to distrust it. */}
{windowApplies && (
<nav className="segmented" aria-label="Leaderboard window">
{WINDOWS.map((w) => (
<Link
key={w.id}
// Carried onto whatever page this is, not back to the
// standings: changing the span of a miner's rank is not a
// reason to stop looking at that miner.
to={href({ ...route, chain, window: w.id })}
aria-current={w.id === route.window ? 'page' : undefined}
title={`${w.blocks.toLocaleString('en-US')} blocks — ${windowSpan(w.blocks, interval)}`}
>
{w.label}
</Link>
))}
</nav>
)}
<div className={`status status-${state.connection}`}>
<span className="status-dot" />

View File

@@ -117,7 +117,7 @@ export function parse(pathname: string): Route {
// same account on every Quantus chain, so the only thing it lacks is which
// chain's figures to show, and the default is the right guess.
if (parts[0] === 'miner' && parts[1]) {
return { ...EMPTY, miner: parts[1].toLowerCase() }
return { ...EMPTY, miner: parts[1].toLowerCase(), window: asWindow(parts[2]) ?? DEFAULT_WINDOW }
}
// Likewise a bare runtime: a spec_version is only meaningful against a chain,
// and the default chain is the one a link without one means.
@@ -132,7 +132,18 @@ export function parse(pathname: string): Route {
const value = parts[2]
if (kind && value) {
if (kind === 'block') return { ...EMPTY, chain, block: value.toLowerCase() }
if (kind === 'miner') return { ...EMPTY, chain, miner: value.toLowerCase() }
// A miner carries a window, because its rank and hashrate are *of* a
// window and a link to one without it means something different from what
// the sender was looking at. In the path rather than a query string, so it
// reads the same way the standings' own window does.
if (kind === 'miner') {
return {
...EMPTY,
chain,
miner: value.toLowerCase(),
window: asWindow(parts[3]) ?? DEFAULT_WINDOW,
}
}
if (kind === 'account') return { ...EMPTY, chain, account: value }
if (kind === 'runtime') return { ...EMPTY, chain, runtime: spec(value) }
}
@@ -155,7 +166,10 @@ export function parse(pathname: string): Route {
export function href(route: Partial<Route>): string {
const chain = route.chain ?? ''
if (route.block) return `/${chain}/block/${route.block}`
if (route.miner) return chain ? `/${chain}/miner/${route.miner}` : `/miner/${route.miner}`
if (route.miner) {
const window = route.window ?? DEFAULT_WINDOW
return chain ? `/${chain}/miner/${route.miner}/${window}` : `/miner/${route.miner}/${window}`
}
if (route.index) return `/${chain}/${route.index}`
if (route.account) return `/${chain}/account/${route.account}`
if (route.runtime !== null && route.runtime !== undefined) {