openvibers/openvibe.bench Commits
Benchmark page: every section shows on a phone; the chips are links (#86)
Changes
@@@ -517,18 +517,15 @@ html, body { margin: 0; background: var(--bg-primary, #0a0f1c); color: var(--tex.br-usethis-details .br-usethis-box { margin: 12px 16px; }.br-usethis-details .br-follow { margin: 0 16px 14px; }--@supports selector(:has(*)) {-- @media (max-width: 640px) {++/* On a phone every section shows (the owner, 2026-10-31: never hide content to shorten); the chips are links that jump++ to Rankings, Tasks or Runs, and each section is compact. */++@media (max-width: 640px) {.br-sec-pick { display: flex; gap: 8px; overflow-x: auto; margin: 14px -16px 0; padding: 2px 16px 4px; scrollbar-width: none; overscroll-behavior-x: contain; }.br-sec-pick::-webkit-scrollbar { display: none; }-- .br-sec-pick input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }-- .br-sec-pick label { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 16px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-secondary); font-size: .86rem; font-weight: 700; white-space: nowrap; cursor: pointer; }-- .br-sec-pick input:checked + label { color: var(--text-primary); border-color: var(--room-accent); background: color-mix(in srgb, var(--room-accent) 14%, transparent); }-- .br-sec-pick input:focus-visible + label { outline: 2px solid var(--room-accent); outline-offset: 2px; }-- .br-sections > section { display: none; margin-top: 16px; }-- .br-sections:has(#br-view-rank:checked) #br-rank,-- .br-sections:has(#br-view-tasks:checked) #br-tasks,-- .br-sections:has(#br-view-runs:checked) #br-runs { display: block; }++ .br-sec-pick a { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 16px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-secondary); font-size: .86rem; font-weight: 700; white-space: nowrap; text-decoration: none; }++ .br-sec-pick a:hover, .br-sec-pick a:focus-visible { color: var(--text-primary); border-color: var(--room-accent); }++ .br-sec-pick a:focus-visible { outline: 2px solid var(--room-accent); outline-offset: 2px; }++ .br-sections > section { margin-top: 22px; scroll-margin-top: 72px; }/* Tasks: one compact line each, number and text, no card, two lines at most. */#br-tasks .br-tasks { gap: 0; margin-top: 4px; }@@@ -554,7 +551,6 @@ html, body { margin: 0; background: var(--bg-primary, #0a0f1c); color: var(--tex#br-runs .br-score-of { font-size: .66rem; }#br-runs .br-score .br-bar { flex: 0 0 24px; height: 3px; margin: 0 0 0 3px; align-self: center; }#br-runs .br-prov { flex: none; padding: 1px 6px; font-size: .68rem; }-- }}.br-fold-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }.br-fold-h { display: flex; align-items: center; gap: 10px; cursor: pointer; }@@@ -415,11 +415,7 @@ ${privateNote}<dl class="br-facts"><div><dt>Tasks</dt><dd>${tasks.length}${hidden ? html` <span class="br-fine">(${hidden} hidden)</span>` : ''}</dd></div><div><dt>Judged by</dt><dd>${judges.length ? judges.map((j) => String(j.type).replace(/_/g, ' ')).join(', ') : '—'}</dd></div><div><dt>Limits</dt><dd>${[limits.ms ? fmtMs(limits.ms) : null, limits.tokens ? `${fmtTokens(limits.tokens)} tokens` : null, limits.usd ? fmtUsd(limits.usd) : null].filter(Boolean).join(' · ') || '—'}</dd></div><div><dt>Verified runs</dt><dd>${entries.reduce((n, e) => n + e.runs, 0)}</dd></div></dl>${owner ? shareBox({ benchmark, shareUrl: share && share.shareUrl, error: share && share.error }) : ''}<div class="br-sections">--<div class="br-sec-pick" role="radiogroup" aria-label="Benchmark sections">--<input type="radio" name="br-view" id="br-view-rank" value="rank" checked><label for="br-view-rank">Rankings</label>--<input type="radio" name="br-view" id="br-view-tasks" value="tasks"><label for="br-view-tasks">Tasks</label>--<input type="radio" name="br-view" id="br-view-runs" value="runs"><label for="br-view-runs">Runs</label>--</div>++<nav class="br-sec-pick" aria-label="Benchmark sections"><a href="#br-rank">Rankings</a><a href="#br-tasks">Tasks</a><a href="#br-runs">Runs</a></nav>${ownBoards? promptBoards(ownBoards): html`<section class="bm-section" id="br-rank" aria-labelledby="br-rank-h"><div class="bm-head-row"><h2 id="br-rank-h">Rankings</h2>${metricTabs(base, metric)}</div>@@@ -103,17 +103,15 @@ function runDoc(benchmark, over = {}) {assert.ok(value.text.includes('aria-current="page"') && value.text.includes('/ $'), 'the value tab is current and shows score per dollar');});-- await check('the phone sections are chips, one per section, with Rankings picked first', async () => {++ await check('the phone sections are all shown, and the chips are links that jump to them', async () => {const res = await t.get(`/benchmarks/${pub.id}`);-- const chips = [...res.text.matchAll(/<input type="radio" name="br-view" id="br-view-([a-z]+)" value="[a-z]+"( checked)?>/g)];-- assert.deepStrictEqual(chips.map((m) => m[1]), ['rank', 'tasks', 'runs'], 'one chip per section, in order');-- assert.deepStrictEqual(chips.filter((m) => m[2]).map((m) => m[1]), ['rank'], 'Rankings is picked first');-- assert.match(res.text, /<div class="br-sections">[\s\S]*id="br-rank"[\s\S]*id="br-tasks"[\s\S]*id="br-runs"[\s\S]*<\/div>/, 'every section stays in the page');++ const chips = [...res.text.matchAll(/<nav class="br-sec-pick" aria-label="Benchmark sections">([\s\S]*?)<\/nav>/g)];++ assert.strictEqual(chips.length, 1, 'one row of chips');++ assert.deepStrictEqual([...chips[0][1].matchAll(/<a href="#(br-[a-z]+)">/g)].map((m) => m[1]), ['br-rank', 'br-tasks', 'br-runs'], 'a link per section, in order');++ assert.ok(!/type="radio" name="br-view"/.test(res.text), 'no chip is a radio: nothing is picked');++ assert.match(res.text, /<div class="br-sections">[\s\S]*id="br-rank"[\s\S]*id="br-tasks"[\s\S]*id="br-runs"[\s\S]*<\/div>/, 'every section is in the page');const css = await t.get('/css/bench.css');-- assert.ok(css.text.includes('@supports selector(:has(*))'), 'the chips are gated on :has()');-- assert.ok(css.text.includes('.br-sections:has(#br-view-rank:checked) #br-rank'), 'Rankings shows when picked');-- assert.ok(css.text.includes('.br-sections:has(#br-view-tasks:checked) #br-tasks'), 'Tasks shows when picked');-- assert.ok(css.text.includes('.br-sections:has(#br-view-runs:checked) #br-runs'), 'Runs shows when picked');++ assert.ok(!/\.br-sections > section \{ display: none/.test(css.text) && !css.text.includes('#br-view-rank:checked'), 'no section is ever hidden (the owner, 2026-10-31)');});await check('badges and embeds are one closed details on a public page, and absent on a private one', async () => {
@@ -517,18 +517,15 @@ html, body { margin: 0; background: var(--bg-primary, #0a0f1c); color: var(--tex
@@ -517,18 +517,15 @@ html, body { margin: 0; background: var(--bg-primary, #0a0f1c); color: var(--tex
.br-usethis-details .br-usethis-box { margin: 12px 16px; }
.br-usethis-details .br-usethis-box { margin: 12px 16px; }
.br-usethis-details .br-follow { margin: 0 16px 14px; }
.br-usethis-details .br-follow { margin: 0 16px 14px; }
-@supports selector(:has(*)) {
- @media (max-width: 640px) {
+/* On a phone every section shows (the owner, 2026-10-31: never hide content to shorten); the chips are links that jump
+ to Rankings, Tasks or Runs, and each section is compact. */
+@media (max-width: 640px) {
.br-sec-pick { display: flex; gap: 8px; overflow-x: auto; margin: 14px -16px 0; padding: 2px 16px 4px; scrollbar-width: none; overscroll-behavior-x: contain; }
.br-sec-pick { display: flex; gap: 8px; overflow-x: auto; margin: 14px -16px 0; padding: 2px 16px 4px; scrollbar-width: none; overscroll-behavior-x: contain; }
.br-sec-pick::-webkit-scrollbar { display: none; }
.br-sec-pick::-webkit-scrollbar { display: none; }
- .br-sec-pick input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
- .br-sec-pick label { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 16px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-secondary); font-size: .86rem; font-weight: 700; white-space: nowrap; cursor: pointer; }
- .br-sec-pick input:checked + label { color: var(--text-primary); border-color: var(--room-accent); background: color-mix(in srgb, var(--room-accent) 14%, transparent); }
- .br-sec-pick input:focus-visible + label { outline: 2px solid var(--room-accent); outline-offset: 2px; }
- .br-sections > section { display: none; margin-top: 16px; }
- .br-sections:has(#br-view-rank:checked) #br-rank,
- .br-sections:has(#br-view-tasks:checked) #br-tasks,
- .br-sections:has(#br-view-runs:checked) #br-runs { display: block; }
+ .br-sec-pick a { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 16px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-secondary); font-size: .86rem; font-weight: 700; white-space: nowrap; text-decoration: none; }
+ .br-sec-pick a:hover, .br-sec-pick a:focus-visible { color: var(--text-primary); border-color: var(--room-accent); }
+ .br-sec-pick a:focus-visible { outline: 2px solid var(--room-accent); outline-offset: 2px; }
+ .br-sections > section { margin-top: 22px; scroll-margin-top: 72px; }
/* Tasks: one compact line each, number and text, no card, two lines at most. */
/* Tasks: one compact line each, number and text, no card, two lines at most. */
#br-tasks .br-tasks { gap: 0; margin-top: 4px; }
#br-tasks .br-tasks { gap: 0; margin-top: 4px; }
@@ -554,7 +551,6 @@ html, body { margin: 0; background: var(--bg-primary, #0a0f1c); color: var(--tex
@@ -554,7 +551,6 @@ html, body { margin: 0; background: var(--bg-primary, #0a0f1c); color: var(--tex
#br-runs .br-score-of { font-size: .66rem; }
#br-runs .br-score-of { font-size: .66rem; }
#br-runs .br-score .br-bar { flex: 0 0 24px; height: 3px; margin: 0 0 0 3px; align-self: center; }
#br-runs .br-score .br-bar { flex: 0 0 24px; height: 3px; margin: 0 0 0 3px; align-self: center; }
#br-runs .br-prov { flex: none; padding: 1px 6px; font-size: .68rem; }
#br-runs .br-prov { flex: none; padding: 1px 6px; font-size: .68rem; }
- }
}
}
.br-fold-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.br-fold-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.br-fold-h { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.br-fold-h { display: flex; align-items: center; gap: 10px; cursor: pointer; }
@@ -415,11 +415,7 @@ ${privateNote}
@@ -415,11 +415,7 @@ ${privateNote}
<dl class="br-facts"><div><dt>Tasks</dt><dd>${tasks.length}${hidden ? html` <span class="br-fine">(${hidden} hidden)</span>` : ''}</dd></div><div><dt>Judged by</dt><dd>${judges.length ? judges.map((j) => String(j.type).replace(/_/g, ' ')).join(', ') : '—'}</dd></div><div><dt>Limits</dt><dd>${[limits.ms ? fmtMs(limits.ms) : null, limits.tokens ? `${fmtTokens(limits.tokens)} tokens` : null, limits.usd ? fmtUsd(limits.usd) : null].filter(Boolean).join(' · ') || '—'}</dd></div><div><dt>Verified runs</dt><dd>${entries.reduce((n, e) => n + e.runs, 0)}</dd></div></dl>
<dl class="br-facts"><div><dt>Tasks</dt><dd>${tasks.length}${hidden ? html` <span class="br-fine">(${hidden} hidden)</span>` : ''}</dd></div><div><dt>Judged by</dt><dd>${judges.length ? judges.map((j) => String(j.type).replace(/_/g, ' ')).join(', ') : '—'}</dd></div><div><dt>Limits</dt><dd>${[limits.ms ? fmtMs(limits.ms) : null, limits.tokens ? `${fmtTokens(limits.tokens)} tokens` : null, limits.usd ? fmtUsd(limits.usd) : null].filter(Boolean).join(' · ') || '—'}</dd></div><div><dt>Verified runs</dt><dd>${entries.reduce((n, e) => n + e.runs, 0)}</dd></div></dl>
${owner ? shareBox({ benchmark, shareUrl: share && share.shareUrl, error: share && share.error }) : ''}
${owner ? shareBox({ benchmark, shareUrl: share && share.shareUrl, error: share && share.error }) : ''}
<div class="br-sections">
<div class="br-sections">
-<div class="br-sec-pick" role="radiogroup" aria-label="Benchmark sections">
-<input type="radio" name="br-view" id="br-view-rank" value="rank" checked><label for="br-view-rank">Rankings</label>
-<input type="radio" name="br-view" id="br-view-tasks" value="tasks"><label for="br-view-tasks">Tasks</label>
-<input type="radio" name="br-view" id="br-view-runs" value="runs"><label for="br-view-runs">Runs</label>
-</div>
+<nav class="br-sec-pick" aria-label="Benchmark sections"><a href="#br-rank">Rankings</a><a href="#br-tasks">Tasks</a><a href="#br-runs">Runs</a></nav>
${ownBoards
${ownBoards
? promptBoards(ownBoards)
? promptBoards(ownBoards)
: html`<section class="bm-section" id="br-rank" aria-labelledby="br-rank-h"><div class="bm-head-row"><h2 id="br-rank-h">Rankings</h2>${metricTabs(base, metric)}</div>
: html`<section class="bm-section" id="br-rank" aria-labelledby="br-rank-h"><div class="bm-head-row"><h2 id="br-rank-h">Rankings</h2>${metricTabs(base, metric)}</div>
@@ -103,17 +103,15 @@ function runDoc(benchmark, over = {}) {
@@ -103,17 +103,15 @@ function runDoc(benchmark, over = {}) {
assert.ok(value.text.includes('aria-current="page"') && value.text.includes('/ $'), 'the value tab is current and shows score per dollar');
assert.ok(value.text.includes('aria-current="page"') && value.text.includes('/ $'), 'the value tab is current and shows score per dollar');
});
});
- await check('the phone sections are chips, one per section, with Rankings picked first', async () => {
+ await check('the phone sections are all shown, and the chips are links that jump to them', async () => {
const res = await t.get(`/benchmarks/${pub.id}`);
const res = await t.get(`/benchmarks/${pub.id}`);
- const chips = [...res.text.matchAll(/<input type="radio" name="br-view" id="br-view-([a-z]+)" value="[a-z]+"( checked)?>/g)];
- assert.deepStrictEqual(chips.map((m) => m[1]), ['rank', 'tasks', 'runs'], 'one chip per section, in order');
- assert.deepStrictEqual(chips.filter((m) => m[2]).map((m) => m[1]), ['rank'], 'Rankings is picked first');
- assert.match(res.text, /<div class="br-sections">[\s\S]*id="br-rank"[\s\S]*id="br-tasks"[\s\S]*id="br-runs"[\s\S]*<\/div>/, 'every section stays in the page');
+ const chips = [...res.text.matchAll(/<nav class="br-sec-pick" aria-label="Benchmark sections">([\s\S]*?)<\/nav>/g)];
+ assert.strictEqual(chips.length, 1, 'one row of chips');
+ assert.deepStrictEqual([...chips[0][1].matchAll(/<a href="#(br-[a-z]+)">/g)].map((m) => m[1]), ['br-rank', 'br-tasks', 'br-runs'], 'a link per section, in order');
+ assert.ok(!/type="radio" name="br-view"/.test(res.text), 'no chip is a radio: nothing is picked');
+ assert.match(res.text, /<div class="br-sections">[\s\S]*id="br-rank"[\s\S]*id="br-tasks"[\s\S]*id="br-runs"[\s\S]*<\/div>/, 'every section is in the page');
const css = await t.get('/css/bench.css');
const css = await t.get('/css/bench.css');
- assert.ok(css.text.includes('@supports selector(:has(*))'), 'the chips are gated on :has()');
- assert.ok(css.text.includes('.br-sections:has(#br-view-rank:checked) #br-rank'), 'Rankings shows when picked');
- assert.ok(css.text.includes('.br-sections:has(#br-view-tasks:checked) #br-tasks'), 'Tasks shows when picked');
- assert.ok(css.text.includes('.br-sections:has(#br-view-runs:checked) #br-runs'), 'Runs shows when picked');
+ assert.ok(!/\.br-sections > section \{ display: none/.test(css.text) && !css.text.includes('#br-view-rank:checked'), 'no section is ever hidden (the owner, 2026-10-31)');
});
});
await check('badges and embeds are one closed details on a public page, and absent on a private one', async () => {
await check('badges and embeds are one closed details on a public page, and absent on a private one', async () => {