ui: a miner and an account are pages, not dialogs
Both were panels that opened above the standings, which is right for a block — "who won this one, and where do they sit" is read against the board, and the ticker row below is what you clicked to get here — and wrong for the other two. A miner's page and an account's page are somebody's own record and the whole subject of the URL that reached them; eleven other miners' rows underneath is the site failing to notice which page it is on. The close buttons go with it. Neither panel opened over something the reader was looking at, so there is nothing to close back to, and the back button and the chain chip already do what it would. "Mark as yours" stays: that is a real control and not navigation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
This commit is contained in:
@@ -156,44 +156,46 @@ export default function App() {
|
||||
// balance on this page wrong and look entirely plausible doing it.
|
||||
decimals={info?.token_decimals ?? 12}
|
||||
symbol={info?.token_symbol ?? ''}
|
||||
onClose={closePanel}
|
||||
/>
|
||||
)}
|
||||
|
||||
{route.miner && chain && (
|
||||
<MinerPanel
|
||||
chain={chain}
|
||||
miner={route.miner}
|
||||
windowName={route.window}
|
||||
onClose={closePanel}
|
||||
/>
|
||||
<MinerPanel chain={chain} miner={route.miner} windowName={route.window} />
|
||||
)}
|
||||
|
||||
<div className="two-col">
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">The Standings</h2>
|
||||
<span className="eyebrow">
|
||||
last {activeWindow.blocks.toLocaleString('en-US')} blocks ·{' '}
|
||||
{windowSpan(activeWindow.blocks, interval)}
|
||||
{pinned.length > 0 && ` · ${pinned.length} marked yours`}
|
||||
</span>
|
||||
</div>
|
||||
<Leaderboard rows={state.leaderboard} chain={chain} ready={state.ready} />
|
||||
</section>
|
||||
{/* A miner and an account are pages, not things opened over the board.
|
||||
Each is somebody's own record and the whole subject of the URL that
|
||||
reached it; leaving eleven other miners' rows underneath is the site
|
||||
failing to notice which page it is on. A block keeps the board,
|
||||
because a block is read *against* it — who won this one, and where do
|
||||
they sit — and the ticker below is the row you clicked to get here. */}
|
||||
{!route.account && !route.miner && (
|
||||
<div className="two-col">
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">The Standings</h2>
|
||||
<span className="eyebrow">
|
||||
last {activeWindow.blocks.toLocaleString('en-US')} blocks ·{' '}
|
||||
{windowSpan(activeWindow.blocks, interval)}
|
||||
{pinned.length > 0 && ` · ${pinned.length} marked yours`}
|
||||
</span>
|
||||
</div>
|
||||
<Leaderboard rows={state.leaderboard} chain={chain} ready={state.ready} />
|
||||
</section>
|
||||
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">Live Blocks</h2>
|
||||
<span className="eyebrow">
|
||||
{state.summary?.block_interval_seconds
|
||||
? `${seconds(state.summary.block_interval_seconds)} apart`
|
||||
: 'measuring'}
|
||||
</span>
|
||||
</div>
|
||||
<BlockTicker blocks={state.blocks} chain={chain} />
|
||||
</section>
|
||||
</div>
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">Live Blocks</h2>
|
||||
<span className="eyebrow">
|
||||
{state.summary?.block_interval_seconds
|
||||
? `${seconds(state.summary.block_interval_seconds)} apart`
|
||||
: 'measuring'}
|
||||
</span>
|
||||
</div>
|
||||
<BlockTicker blocks={state.blocks} chain={chain} />
|
||||
</section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<footer className="footer">
|
||||
<span>
|
||||
|
||||
@@ -148,14 +148,12 @@ export function AccountPanel({
|
||||
address,
|
||||
decimals,
|
||||
symbol,
|
||||
onClose,
|
||||
}: {
|
||||
chain: string
|
||||
address: string
|
||||
/** The chain's token decimals; 12 on Quantus, but read rather than assumed. */
|
||||
decimals: number
|
||||
symbol: string
|
||||
onClose: () => void
|
||||
}) {
|
||||
const [detail, setDetail] = useState<AccountDetail | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
@@ -205,9 +203,10 @@ export function AccountPanel({
|
||||
)}
|
||||
</dl>
|
||||
</div>
|
||||
<button className="segmented panel-button" onClick={onClose}>
|
||||
Close
|
||||
</button>
|
||||
{/* No close button. This is a URL somebody navigated to, not a dialog
|
||||
that opened over something they were reading — there is nothing
|
||||
underneath to get back to, and the back button and the chain chip
|
||||
both already do what a close button would. */}
|
||||
</div>
|
||||
|
||||
{error && <p className="empty">{error}</p>}
|
||||
|
||||
@@ -22,12 +22,10 @@ export function MinerPanel({
|
||||
chain,
|
||||
miner,
|
||||
windowName,
|
||||
onClose,
|
||||
}: {
|
||||
chain: string
|
||||
miner: string
|
||||
windowName: WindowName
|
||||
onClose: () => void
|
||||
}) {
|
||||
const [detail, setDetail] = useState<MinerDetail | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
@@ -90,39 +88,17 @@ export function MinerPanel({
|
||||
<dd className="numeral">{miner}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
|
||||
<button
|
||||
className="segmented"
|
||||
style={{
|
||||
padding: '7px 13px',
|
||||
font: 'inherit',
|
||||
fontSize: 12,
|
||||
letterSpacing: '0.1em',
|
||||
textTransform: 'uppercase',
|
||||
color: mine ? 'var(--accent-bright)' : 'var(--text-secondary)',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
aria-pressed={mine}
|
||||
onClick={() => toggle(miner)}
|
||||
>
|
||||
{mine ? '★ Yours' : '☆ Mark as yours'}
|
||||
</button>
|
||||
<button
|
||||
className="segmented"
|
||||
style={{
|
||||
padding: '7px 13px',
|
||||
font: 'inherit',
|
||||
fontSize: 12,
|
||||
letterSpacing: '0.1em',
|
||||
textTransform: 'uppercase',
|
||||
color: 'var(--text-secondary)',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={onClose}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
{/* No close button: this is a URL somebody navigated to, not a dialog
|
||||
that opened over something they were reading. The back button and
|
||||
the chain chip both already do what it would. */}
|
||||
<button
|
||||
className="segmented panel-button"
|
||||
style={{ color: mine ? 'var(--accent-bright)' : 'var(--text-secondary)' }}
|
||||
aria-pressed={mine}
|
||||
onClick={() => toggle(miner)}
|
||||
>
|
||||
{mine ? '★ Yours' : '☆ Mark as yours'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{error && <p className="empty">{error}</p>}
|
||||
|
||||
Reference in New Issue
Block a user