From bb3731bcd9ff09a7a6c5410d473567b4cf4f7fad Mon Sep 17 00:00:00 2001 From: Glary-Bot Date: Fri, 15 May 2026 21:23:25 +0000 Subject: [PATCH 1/2] fix: redraw canvas and resync slot layouts on bottom-panel toggle Belt-and-braces for the bottom-panel/node-displacement bug. The PrimeVue Splitter changes the canvas container size which triggers the canvas ResizeObserver and the per-node Vue ResizeObservers, but both have failure modes during animated transitions (RAF batching, suspended-tab handling, stale viewport state on the first measurement). Explicitly request a slot layout resync and setDirty(true, true) on the canvas when bottomPanelVisible flips, so links stay aligned with slot connectors regardless of what the RO chain did during the transition. Mirrors the existing linearMode watcher pattern in this file. --- src/components/graph/GraphCanvas.vue | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index 67ef64d7445..6805fbc9cf5 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -181,6 +181,7 @@ import { useCommandStore } from '@/stores/commandStore' import { useExecutionStore } from '@/stores/executionStore' import { useExecutionErrorStore } from '@/stores/executionErrorStore' import { useNodeDefStore } from '@/stores/nodeDefStore' +import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore' import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' import { useSearchBoxStore } from '@/stores/workspace/searchBoxStore' import { useAppMode } from '@/composables/useAppMode' @@ -297,6 +298,18 @@ watch( } ) +const { bottomPanelVisible } = storeToRefs(useBottomPanelStore()) +watch(bottomPanelVisible, () => { + // The splitter resizes the canvas container, which triggers the canvas + // ResizeObserver and (eventually) the per-node Vue ResizeObservers. Force a + // slot/link redraw once the splitter has settled so links stay aligned with + // slot connectors even if any RO callback was missed or measured stale + // viewport state during the transition. + if (!canvasStore.canvas) return + requestSlotLayoutSyncForAllNodes() + canvasStore.canvas.setDirty(true, true) +}) + function onLinkOverlayReady(el: HTMLCanvasElement) { if (!canvasStore.canvas) return canvasStore.canvas.overlayCanvas = el From 9529182117b7a5b0fc0ebcc730c4eba85db89c76 Mon Sep 17 00:00:00 2001 From: Glary-Bot Date: Fri, 15 May 2026 21:28:19 +0000 Subject: [PATCH 2/2] fix: watch composite bottom-panel rendered condition incl. focusMode Address review: bottomPanelVisible alone misses the focusMode case (splitter hides the panel when focusMode is on, regardless of the store flag). Compose the same condition the splitter uses so toggling focusMode while the panel is open also triggers the redraw/resync. --- src/components/graph/GraphCanvas.vue | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index 6805fbc9cf5..19aaddcd841 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -299,7 +299,14 @@ watch( ) const { bottomPanelVisible } = storeToRefs(useBottomPanelStore()) -watch(bottomPanelVisible, () => { +// Mirror the splitter's rendered condition: the bottom panel is hidden when +// focusMode is on, regardless of bottomPanelVisible (see +// LiteGraphCanvasSplitterOverlay.vue). Watching the composite means entering +// or leaving focus mode while the panel is open also triggers the redraw. +const bottomPanelRendered = computed( + () => bottomPanelVisible.value && !workspaceStore.focusMode +) +watch(bottomPanelRendered, () => { // The splitter resizes the canvas container, which triggers the canvas // ResizeObserver and (eventually) the per-node Vue ResizeObservers. Force a // slot/link redraw once the splitter has settled so links stay aligned with