Michael Rabinovich Cursor commited on
Commit ·
5dd0c03
1
Parent(s): 08eae45
leaderboard: lock GT row + header in a capped gallery scroll box
Browse filesMake the gallery a scroll container capped at ~78% of the visible
viewport so the column header and ground-truth row stay pinned (sticky)
at the top while submissions scroll inside it. The cap is set from the
parent viewport in JS and the iframe is sized to the (bounded) content,
so the page stays compact and shows no scrollbar when the rows are
shorter than the cap.
Co-authored-by: Cursor <cursoragent@cursor.com>
- gallery.py +34 -6
gallery.py
CHANGED
|
@@ -250,7 +250,17 @@ body {
|
|
| 250 |
.section-caption { margin: 0 0 16px; font-size: 12.5px; color: var(--ink-soft); line-height: 1.5; }
|
| 251 |
.section-caption b { color: var(--ink); font-weight: 600; }
|
| 252 |
|
| 253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
.grid-head, .grow {
|
| 255 |
display: grid;
|
| 256 |
grid-template-columns: 52px minmax(200px, 1.3fr) 160px repeat(var(--ncol, 4), minmax(140px, 1fr));
|
|
@@ -633,9 +643,24 @@ function syncHeadHeight() {
|
|
| 633 |
if (head) document.documentElement.style.setProperty('--head-h', head.offsetHeight + 'px');
|
| 634 |
}
|
| 635 |
|
| 636 |
-
//
|
| 637 |
-
//
|
| 638 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 639 |
function fitIframe() {
|
| 640 |
try {
|
| 641 |
const fe = window.frameElement;
|
|
@@ -644,8 +669,11 @@ function fitIframe() {
|
|
| 644 |
}
|
| 645 |
|
| 646 |
buildGallery();
|
|
|
|
| 647 |
fitIframe();
|
| 648 |
-
|
|
|
|
|
|
|
| 649 |
if (window.ResizeObserver) new ResizeObserver(fitIframe).observe(document.body);
|
| 650 |
-
if (document.fonts && document.fonts.ready) document.fonts.ready.then(
|
| 651 |
"""
|
|
|
|
| 250 |
.section-caption { margin: 0 0 16px; font-size: 12.5px; color: var(--ink-soft); line-height: 1.5; }
|
| 251 |
.section-caption b { color: var(--ink); font-weight: 600; }
|
| 252 |
|
| 253 |
+
/* Scroll container: the column header + ground-truth row are `position:
|
| 254 |
+
sticky` against this box, so they stay locked at the top while the
|
| 255 |
+
submission rows scroll. `--gallery-max` is set in JS from the parent
|
| 256 |
+
viewport height; the px value here is only the pre-script fallback.
|
| 257 |
+
When the content is shorter than the cap, `overflow:auto` shows no
|
| 258 |
+
scrollbar and the box just sizes to its rows. */
|
| 259 |
+
.gallery {
|
| 260 |
+
background: var(--panel); border: 1px solid var(--line);
|
| 261 |
+
border-radius: var(--radius); box-shadow: var(--shadow); position: relative;
|
| 262 |
+
max-height: var(--gallery-max, 640px); overflow: auto;
|
| 263 |
+
}
|
| 264 |
.grid-head, .grow {
|
| 265 |
display: grid;
|
| 266 |
grid-template-columns: 52px minmax(200px, 1.3fr) 160px repeat(var(--ncol, 4), minmax(140px, 1fr));
|
|
|
|
| 643 |
if (head) document.documentElement.style.setProperty('--head-h', head.offsetHeight + 'px');
|
| 644 |
}
|
| 645 |
|
| 646 |
+
// Cap the scroll box at a fraction of the *visible* (parent) viewport so the
|
| 647 |
+
// GT row + header lock while submissions scroll inside it, without making the
|
| 648 |
+
// page tall. When the rows are shorter than the cap the box just sizes to them
|
| 649 |
+
// (no scrollbar). Reads the parent viewport (same-origin srcdoc); no-ops to the
|
| 650 |
+
// CSS px fallback if that access is blocked.
|
| 651 |
+
function capGallery() {
|
| 652 |
+
try {
|
| 653 |
+
const pv = window.parent;
|
| 654 |
+
if (pv && pv.innerHeight) {
|
| 655 |
+
const cap = Math.max(360, Math.round(pv.innerHeight * 0.78));
|
| 656 |
+
document.documentElement.style.setProperty('--gallery-max', cap + 'px');
|
| 657 |
+
}
|
| 658 |
+
} catch (e) { /* keep CSS fallback */ }
|
| 659 |
+
}
|
| 660 |
+
|
| 661 |
+
// Size the iframe to its content so the page is as compact as the (capped)
|
| 662 |
+
// gallery -- no oversized fixed box, no empty space when there are few rows.
|
| 663 |
+
// No-ops if frameElement is unreadable (the wrapper then keeps its CSS height).
|
| 664 |
function fitIframe() {
|
| 665 |
try {
|
| 666 |
const fe = window.frameElement;
|
|
|
|
| 669 |
}
|
| 670 |
|
| 671 |
buildGallery();
|
| 672 |
+
capGallery();
|
| 673 |
fitIframe();
|
| 674 |
+
function relayout() { syncHeadHeight(); capGallery(); fitIframe(); }
|
| 675 |
+
window.addEventListener('resize', relayout);
|
| 676 |
+
try { window.parent.addEventListener('resize', relayout); } catch (e) { /* ignore */ }
|
| 677 |
if (window.ResizeObserver) new ResizeObserver(fitIframe).observe(document.body);
|
| 678 |
+
if (document.fonts && document.fonts.ready) document.fonts.ready.then(relayout);
|
| 679 |
"""
|