fix(web): mark a section's nav link on its subjects' pages, not only its index
ci / gate (push) Successful in 4m26s
deploy / validate (push) Skipped
deploy / build (push) Successful in 1m26s
deploy / deploy-api (push) Skipped
deploy / deploy-web (push) Successful in 6s

`/quantus/market/near-intents` marked nothing in the section nav, nor did a
block, account or runtime page: the nav tested the index plus a hand-kept list
of exceptions that every newer section had missed. `sectionOf` in
lib/routes.ts now answers it once, over every subject field. Block zero stays
with Genesis alone.

Closes #40

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015pkwBsR54NRmZyU4QVhvfj
This commit is contained in:
2026-10-06 14:10:10 +03:00
co-authored by Claude Opus 5.5
parent 7cd2197997
commit c483d51dc7
2 changed files with 31 additions and 11 deletions
+4 -11
View File
@@ -15,7 +15,7 @@
import { Link } from 'react-router-dom'
import type { Window as WindowName } from '../api/generated/Window'
import { href, isStandings, type Route, SECTIONS } from '../lib/routes'
import { href, isStandings, type Route, SECTIONS, sectionOf } from '../lib/routes'
export function SectionNav({
chain,
@@ -31,6 +31,7 @@ export function SectionNav({
if (!chain) return null
// The standings are current when nothing else is: no panel open, no index.
const onStandings = isStandings(route)
const current = sectionOf(route)
return (
<nav className="sections" aria-label="Section">
@@ -57,16 +58,8 @@ export function SectionNav({
key={s.id}
to={href({ chain, index: s.id })}
className="section-link"
// A call's own page belongs to the Calls section, so the nav marks
// it there rather than nowhere.
aria-current={
route.index === s.id ||
(s.id === 'call' && route.call !== null) ||
(s.id === 'event' && route.event !== null) ||
(s.id === 'node' && route.node !== null)
? 'page'
: undefined
}
// A subject's own page belongs to the section that indexes it.
aria-current={current === s.id ? 'page' : undefined}
>
{s.label}
</Link>
+27
View File
@@ -314,6 +314,33 @@ export function isStandings(route: Route): boolean {
)
}
/**
* The section a route belongs to, for the nav to mark.
*
* A subject's own page belongs to the section that indexes it:
* `/quantus/market/near-intents` is in Markets as much as `/quantus/market`
* is. The nav used to test the index plus a hand-kept list of exceptions, and
* every section added after the list was written — markets, blocks, accounts,
* runtimes — went unmarked on its own pages. Same lesson as {@link isStandings}:
* one place, written over every subject field.
*
* Block zero is the exception: the nav has a Genesis link for exactly that
* block, and marking Blocks beside it would mark two places at once. A miner
* belongs to no section — the standings are its index, and they have their own
* link.
*/
export function sectionOf(route: Route): SectionName | null {
if (route.index) return route.index
if (route.block !== null) return route.block === '0' ? null : 'block'
if (route.account !== null) return 'account'
if (route.runtime !== null) return 'runtime'
if (route.call !== null) return 'call'
if (route.event !== null) return 'event'
if (route.node !== null) return 'node'
if (route.market !== null) return 'market'
return null
}
/** The canonical path for a route. The inverse of {@link parse}. */
export function href(route: Partial<Route>): string {
const chain = route.chain ?? ''