mirror of
https://github.com/penpot/penpot.git
synced 2026-08-18 02:39:02 +00:00
🐛 Fix runaway graph panel growth and blank canvas; drop Expand button
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 <alvorithm@teje.ro>
This commit is contained in:
parent
6a26687ab6
commit
331bd4e3e5
@ -11,7 +11,10 @@ Graph Console
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<main class="dashboard">
|
<main class="dashboard">
|
||||||
<section class="widget" style="max-width: none;">
|
<!-- flex: 1 1 0 + min-width: 0: size this .dashboard flex item from the
|
||||||
|
viewport, never from content — content-driven growth (e.g. the G6
|
||||||
|
canvas) would otherwise feed back into column width. -->
|
||||||
|
<section class="widget" style="max-width: none; flex: 1 1 0; min-width: 0;">
|
||||||
<p><a href="/dbg">← Back to debug</a></p>
|
<p><a href="/dbg">← Back to debug</a></p>
|
||||||
|
|
||||||
<div style="display: flex; gap: 16px; align-items: flex-start;">
|
<div style="display: flex; gap: 16px; align-items: flex-start;">
|
||||||
@ -151,7 +154,6 @@ Graph Console
|
|||||||
style="flex: 1 1 auto; min-width: 0;">
|
style="flex: 1 1 auto; min-width: 0;">
|
||||||
<fieldset id="graph-view-panel">
|
<fieldset id="graph-view-panel">
|
||||||
<legend>Graph view
|
<legend>Graph view
|
||||||
<button type="button" id="graph-maximize" style="margin-left: 1em;">Expand</button>
|
|
||||||
<label style="margin-left: 1em; font-size: 12px; font-weight: normal;">
|
<label style="margin-left: 1em; font-size: 12px; font-weight: normal;">
|
||||||
<input type="checkbox" id="graph-fold-toggle" /> fold containers
|
<input type="checkbox" id="graph-fold-toggle" /> fold containers
|
||||||
</label>
|
</label>
|
||||||
@ -173,7 +175,7 @@ Graph Console
|
|||||||
</desc>
|
</desc>
|
||||||
<div id="graph-legend" style="font-size: 12px; margin: 4px 0;"></div>
|
<div id="graph-legend" style="font-size: 12px; margin: 4px 0;"></div>
|
||||||
<div id="graph-canvas"
|
<div id="graph-canvas"
|
||||||
style="width: 100%; height: 600px; border: 1px solid #ccc; background: #fff;"></div>
|
style="width: 100%; height: 600px; border: 1px solid #ccc; background: #fff; overflow: hidden;"></div>
|
||||||
<div id="graph-view-status" style="color: #666; font-size: 12px;"></div>
|
<div id="graph-view-status" style="color: #666; font-size: 12px;"></div>
|
||||||
<button type="button" id="graph-render-anyway" style="display: none;">Render anyway</button>
|
<button type="button" id="graph-render-anyway" style="display: none;">Render anyway</button>
|
||||||
<button type="button" id="graph-filter-reset" style="display: none;">Show full graph</button>
|
<button type="button" id="graph-filter-reset" style="display: none;">Show full graph</button>
|
||||||
@ -190,6 +192,13 @@ Graph Console
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 8px;
|
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 {
|
#graph-view-column.graph-view-expanded {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
@ -512,7 +521,6 @@ Graph Console
|
|||||||
container: "graph-canvas",
|
container: "graph-canvas",
|
||||||
data: g6data,
|
data: g6data,
|
||||||
autoFit: "view",
|
autoFit: "view",
|
||||||
autoResize: true,
|
|
||||||
animation: animate,
|
animation: animate,
|
||||||
padding: 20,
|
padding: 20,
|
||||||
node: {
|
node: {
|
||||||
@ -582,7 +590,9 @@ Graph Console
|
|||||||
+ '<span style="color: ' + s.color + '; font-size: 14px;">'
|
+ '<span style="color: ' + s.color + '; font-size: 14px;">'
|
||||||
+ (GLYPH_CHARS[s.glyph] || "●") + '</span> '
|
+ (GLYPH_CHARS[s.glyph] || "●") + '</span> '
|
||||||
+ escapeHtml(table) + "</span>";
|
+ escapeHtml(table) + "</span>";
|
||||||
}).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) {
|
function graphStatusText(data) {
|
||||||
@ -955,8 +965,8 @@ Graph Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
// In-page expand (no Fullscreen API): keeps browser chrome and window
|
// In-page expand (no Fullscreen API): keeps browser chrome and window
|
||||||
// manager splits usable while the graph takes the whole page.
|
// manager splits usable while the graph takes the whole page. Entered
|
||||||
const maximizeBtn = document.getElementById("graph-maximize");
|
// via the toolbar's expand icon; exited via its exit icon or Esc.
|
||||||
const graphColumn = document.getElementById("graph-view-column");
|
const graphColumn = document.getElementById("graph-view-column");
|
||||||
|
|
||||||
function resizeGraphSoon() {
|
function resizeGraphSoon() {
|
||||||
@ -973,13 +983,16 @@ Graph Console
|
|||||||
|
|
||||||
function setExpanded(expanded) {
|
function setExpanded(expanded) {
|
||||||
graphColumn.classList.toggle("graph-view-expanded", expanded);
|
graphColumn.classList.toggle("graph-view-expanded", expanded);
|
||||||
maximizeBtn.textContent = expanded ? "Restore (Esc)" : "Expand";
|
|
||||||
resizeGraphSoon();
|
resizeGraphSoon();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Follow container size (window resizes, flex reflow). Only setSize —
|
// Follow container size (G6's autoResize is inert on this build).
|
||||||
// the user's viewport must persist; explicit re-fit is the toolbar's
|
// Safe only because the container's width is viewport-driven and can
|
||||||
// auto-fit (or expand/restore, which do fitView via resizeGraphSoon).
|
// 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");
|
const canvasEl = document.getElementById("graph-canvas");
|
||||||
if (typeof ResizeObserver !== "undefined" && canvasEl) {
|
if (typeof ResizeObserver !== "undefined" && canvasEl) {
|
||||||
let resizeRaf = null;
|
let resizeRaf = null;
|
||||||
@ -987,19 +1000,18 @@ Graph Console
|
|||||||
if (resizeRaf) return;
|
if (resizeRaf) return;
|
||||||
resizeRaf = requestAnimationFrame(function () {
|
resizeRaf = requestAnimationFrame(function () {
|
||||||
resizeRaf = null;
|
resizeRaf = null;
|
||||||
if (g6graph) {
|
if (!g6graph) return;
|
||||||
try {
|
try {
|
||||||
g6graph.setSize(canvasEl.clientWidth, canvasEl.clientHeight);
|
const cur = g6graph.getSize();
|
||||||
} catch (_err) { /* instance mid-recreate */ }
|
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);
|
}).observe(canvasEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maximizeBtn && graphColumn) {
|
if (graphColumn) {
|
||||||
maximizeBtn.addEventListener("click", function () {
|
|
||||||
setExpanded(!graphColumn.classList.contains("graph-view-expanded"));
|
|
||||||
});
|
|
||||||
document.addEventListener("keydown", function (ev) {
|
document.addEventListener("keydown", function (ev) {
|
||||||
if (ev.key === "Escape"
|
if (ev.key === "Escape"
|
||||||
&& graphColumn.classList.contains("graph-view-expanded")) {
|
&& graphColumn.classList.contains("graph-view-expanded")) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user