From a83138b3cecf8d2044bec1b7a6dc791e67effbc0 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 17 Sep 2026 15:25:38 -0400 Subject: [PATCH] Make the row-label floor three characters, not 130px MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 130px was far too wide — it was a guess, and it turned the row labels into a quarter of the sheet. The floor only needs to stop a column coming back unusable after a layout restore, not to fit anything. Three characters, measured in the grid's own font plus its cell padding rather than fixed in pixels, so it survives a theme or zoom change. Co-Authored-By: Claude Opus 5 (1M context) --- ui/src/views/Forecast.jsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/ui/src/views/Forecast.jsx b/ui/src/views/Forecast.jsx index 02d7aa1..b85d8fc 100644 --- a/ui/src/views/Forecast.jsx +++ b/ui/src/views/Forecast.jsx @@ -1098,22 +1098,34 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio // A minimum leaves the default spacing alone where it is already reasonable and // only intervenes where a column came back unusably narrow. Anything already // wider — set by dragging, or recorded in a layout — is untouched. - const MIN_ROW_LABEL_W = 130 + // Three characters, measured in the grid's own font rather than guessed in + // pixels, so it holds up if the theme or zoom changes. + const MIN_ROW_LABEL_CHARS = 3 async function ensureRowLabelWidth() { const grid = (await viewerRef.current?.getPlugin())?.regular_table if (!grid?.saveColumnSizes) return + + const cells = [...grid.querySelectorAll('tbody th')] const idxs = new Set() - for (const cell of grid.querySelectorAll('tbody th')) { + for (const cell of cells) { const m = [...cell.classList].map(c => /^rt-col-(\d+)$/.exec(c)).find(Boolean) if (m) idxs.add(Number(m[1])) } if (idxs.size === 0) return + const style = getComputedStyle(cells[0]) + const ctx = (ensureRowLabelWidth._ctx ||= document.createElement('canvas').getContext('2d')) + ctx.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}` + const min = Math.ceil( + ctx.measureText('0'.repeat(MIN_ROW_LABEL_CHARS)).width + + parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + ) + const sizes = { ...grid.saveColumnSizes() } let changed = false for (const idx of idxs) { - if ((sizes[idx] ?? 0) < MIN_ROW_LABEL_W) { sizes[idx] = MIN_ROW_LABEL_W; changed = true } + if ((sizes[idx] ?? 0) < min) { sizes[idx] = min; changed = true } } if (!changed) return grid.restoreColumnSizes(sizes)