From 331bd4e3e529088f7f9baee4332d38e4f97b28c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Tejero=20Cantero?= Date: Thu, 16 Jul 2026 10:27:51 +0200 Subject: [PATCH] :bug: Fix runaway graph panel growth and blank canvas; drop Expand button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of 'graph flashes on load then disappears' plus unbounded horizontal growth of the graph panel: fieldsets default to min-inline-size: min-content, so #graph-view-panel sized to its content, and the new ResizeObserver->setSize path closed a feedback loop (setSize -> slightly wider G6 canvas -> wider fieldset -> wider .dashboard flex column -> observer fires) that grew the page ~10px per frame and wiped the painted canvas on every step. Fix severs the feedback path: #graph-view-panel gets min-inline-size: 0, #graph-canvas gets overflow: hidden, and the page section gets flex: 1 1 0 with min-width: 0 so column widths are viewport-driven, never content-driven. This also fixes the original narrow-window scrollbars defect for real. The observer stays (guarded by a current-size comparison) because G6's autoResize is inert on this UMD build (verified: window resizes left the canvas size untouched); the inert autoResize flag is dropped. Legend items now join with spaces so the nowrap spans can wrap between entries. Also removes the header Expand button - the toolbar's expand/exit icons cover it, Esc still restores. Verified against the running devenv with a logged-in profile and variants_simple loaded: graph renders and persists, widths stable over multiple seconds at 1400px and 1000px viewports with no horizontal overflow, canvas follows both window shrink and grow, toolbar expand gives a full-page canvas and Esc restores. Signed-off-by: Álvaro Tejero Cantero --- .../app/templates/graph-console.tmpl | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/backend/resources/app/templates/graph-console.tmpl b/backend/resources/app/templates/graph-console.tmpl index a65ff17cd0..5732a000a6 100644 --- a/backend/resources/app/templates/graph-console.tmpl +++ b/backend/resources/app/templates/graph-console.tmpl @@ -11,7 +11,10 @@ Graph Console
-
+ +

← Back to debug

@@ -151,7 +154,6 @@ Graph Console style="flex: 1 1 auto; min-width: 0;">
Graph view - @@ -173,7 +175,7 @@ Graph Console
+ style="width: 100%; height: 600px; border: 1px solid #ccc; background: #fff; overflow: hidden;">
@@ -190,6 +192,13 @@ Graph Console position: sticky; top: 8px; } + /* Fieldsets default to min-inline-size: min-content, so the panel could + never shrink below its content and grew with the G6 canvas instead + (content -> fieldset -> column -> canvas feedback). Let it shrink; + the legend wraps and the canvas clips. */ + #graph-view-panel { + min-inline-size: 0; + } #graph-view-column.graph-view-expanded { position: fixed; inset: 0; @@ -512,7 +521,6 @@ Graph Console container: "graph-canvas", data: g6data, autoFit: "view", - autoResize: true, animation: animate, padding: 20, node: { @@ -582,7 +590,9 @@ Graph Console + '' + (GLYPH_CHARS[s.glyph] || "●") + ' ' + escapeHtml(table) + ""; - }).join(""); + // join with a space: the spans are nowrap, so the separator is the + // only soft-wrap opportunity in the legend row + }).join(" "); } function graphStatusText(data) { @@ -955,8 +965,8 @@ Graph Console } // In-page expand (no Fullscreen API): keeps browser chrome and window - // manager splits usable while the graph takes the whole page. - const maximizeBtn = document.getElementById("graph-maximize"); + // manager splits usable while the graph takes the whole page. Entered + // via the toolbar's expand icon; exited via its exit icon or Esc. const graphColumn = document.getElementById("graph-view-column"); function resizeGraphSoon() { @@ -973,13 +983,16 @@ Graph Console function setExpanded(expanded) { graphColumn.classList.toggle("graph-view-expanded", expanded); - maximizeBtn.textContent = expanded ? "Restore (Esc)" : "Expand"; resizeGraphSoon(); } - // Follow container size (window resizes, flex reflow). Only setSize — - // the user's viewport must persist; explicit re-fit is the toolbar's - // auto-fit (or expand/restore, which do fitView via resizeGraphSoon). + // Follow container size (G6's autoResize is inert on this build). + // Safe only because the container's width is viewport-driven and can + // never follow the canvas: the fieldset's min-content floor is removed + // (#graph-view-panel min-inline-size: 0) and #graph-canvas clips + // (overflow: hidden). Without both, observer -> setSize -> wider canvas + // -> wider column -> observer is a runaway growth loop that also wipes + // the painted canvas on every step. const canvasEl = document.getElementById("graph-canvas"); if (typeof ResizeObserver !== "undefined" && canvasEl) { let resizeRaf = null; @@ -987,19 +1000,18 @@ Graph Console if (resizeRaf) return; resizeRaf = requestAnimationFrame(function () { resizeRaf = null; - if (g6graph) { - try { - g6graph.setSize(canvasEl.clientWidth, canvasEl.clientHeight); - } catch (_err) { /* instance mid-recreate */ } - } + if (!g6graph) return; + try { + const cur = g6graph.getSize(); + const w = canvasEl.clientWidth; + const h = canvasEl.clientHeight; + if (!cur || cur[0] !== w || cur[1] !== h) g6graph.setSize(w, h); + } catch (_err) { /* instance mid-recreate */ } }); }).observe(canvasEl); } - if (maximizeBtn && graphColumn) { - maximizeBtn.addEventListener("click", function () { - setExpanded(!graphColumn.classList.contains("graph-view-expanded")); - }); + if (graphColumn) { document.addEventListener("keydown", function (ev) { if (ev.key === "Escape" && graphColumn.classList.contains("graph-view-expanded")) {