From a4fc36352dfb4aef086bf46fe2d5e3a86b2d5adb Mon Sep 17 00:00:00 2001 From: Michael Pilosov Date: Wed, 22 Apr 2026 16:57:15 -0600 Subject: [PATCH] =?UTF-8?q?compare:=20axes=20dropdown=20combines=20sync=20?= =?UTF-8?q?(scaled/locked)=20=C3=97=20aspect=20(1:1/3:2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Canvas height now derives from column width via aspect-ratio (CSS custom prop --canvas-aspect set by JS on the grid host), with --panel-h as a ceiling. Dropdown options: scaled/locked × 1:1/3:2. Default scaled 3:2. Legacy 'independent'/'locked' values still parse. Canvas resizes after aspect changes via requestAnimationFrame. --- app/web/static/compare.js | 2 +- app/web/static/panel-grid.js | 24 +++++++++++++++++++----- app/web/static/run-modal.js | 2 +- app/web/static/style.css | 7 +++++-- app/web/templates/compare.html | 12 ++++++++---- app/web/templates/index.html | 10 ++++++---- 6 files changed, 40 insertions(+), 17 deletions(-) diff --git a/app/web/static/compare.js b/app/web/static/compare.js index 3f89aee..9fefffd 100644 --- a/app/web/static/compare.js +++ b/app/web/static/compare.js @@ -1,7 +1,7 @@ // compare.js — thin shim that parses ?stem=…&stem=… (legacy ?a=&b=) and // hands off to panel-grid.js. -import { mountPanels } from './panel-grid.js?v=1'; +import { mountPanels } from './panel-grid.js?v=4'; const params = new URLSearchParams(window.location.search); let stems = params.getAll('stem').filter(Boolean); diff --git a/app/web/static/panel-grid.js b/app/web/static/panel-grid.js index 22e5124..194819f 100644 --- a/app/web/static/panel-grid.js +++ b/app/web/static/panel-grid.js @@ -628,9 +628,21 @@ export function mountPanels({ host, controls, stems }) { } } - function applySync() { - const mode = syncSel ? syncSel.value : 'independent'; - if (mode === 'locked' && live.length > 1) { + function parseAxes(value) { + // Accepted: "scaled-1x1", "scaled-3x2", "locked-1x1", "locked-3x2", + // plus legacy "independent" / "locked" (assume 1:1). + const v = value || 'scaled-1x1'; + if (v === 'independent') return { sync: 'scaled', aspect: '1 / 1' }; + if (v === 'locked') return { sync: 'locked', aspect: '1 / 1' }; + const [sync, ratio] = v.split('-'); + const aspect = ratio === '3x2' ? '3 / 2' : '1 / 1'; + return { sync: sync === 'locked' ? 'locked' : 'scaled', aspect }; + } + + function applyAxes() { + const { sync, aspect } = parseAxes(syncSel ? syncSel.value : 'scaled-3x2'); + host.style.setProperty('--canvas-aspect', aspect); + if (sync === 'locked' && live.length > 1) { let xmin = +Infinity, xmax = -Infinity, ymin = +Infinity, ymax = -Infinity; for (const s of live) { const b = s.panel.data.bounds; @@ -644,9 +656,11 @@ export function mountPanels({ host, controls, stems }) { } else { for (const s of live) s.panel.setBounds(s.panel.data.bounds); } + // Canvas size changes with aspect — let the panels re-fit next frame. + requestAnimationFrame(() => { for (const s of live) s.panel.resize(); }); } - if (syncSel) onCtl(syncSel, 'change', applySync); - applySync(); + if (syncSel) onCtl(syncSel, 'change', applyAxes); + applyAxes(); let playing = false; let lastTs = 0; diff --git a/app/web/static/run-modal.js b/app/web/static/run-modal.js index 4764c88..c996d0a 100644 --- a/app/web/static/run-modal.js +++ b/app/web/static/run-modal.js @@ -1,7 +1,7 @@ // run-modal.js — homepage click-hijack for embedding links. Opens a // that renders the run's embedding via panel-grid.js. -import { mountPanels } from './panel-grid.js?v=1'; +import { mountPanels } from './panel-grid.js?v=4'; const dialog = document.getElementById('run-modal'); const host = document.getElementById('modal-panel-host'); diff --git a/app/web/static/style.css b/app/web/static/style.css index be5859f..f23461d 100644 --- a/app/web/static/style.css +++ b/app/web/static/style.css @@ -1587,10 +1587,13 @@ button.submit:disabled { background: var(--faint); border-color: var(--faint); c .compare-canvas { position: relative; - flex: 1 1 auto; + flex: 0 0 auto; min-height: 0; background: var(--picker-panel, var(--panel)); - height: var(--panel-h); + /* Height derives from column width × aspect ratio. Controlled by the + axes dropdown via --canvas-aspect on the grid. --panel-h is the cap. */ + aspect-ratio: var(--canvas-aspect, 1 / 1); + max-height: var(--panel-h); } .compare-canvas canvas { diff --git a/app/web/templates/compare.html b/app/web/templates/compare.html index 5b3adcf..f9ec60b 100644 --- a/app/web/templates/compare.html +++ b/app/web/templates/compare.html @@ -4,7 +4,7 @@ embedding notebook · compare - + - + + + diff --git a/app/web/templates/index.html b/app/web/templates/index.html index 16bed4d..7bf6295 100644 --- a/app/web/templates/index.html +++ b/app/web/templates/index.html @@ -4,7 +4,7 @@ embedding notebook - + - +