From ea2f1c36c572d0b0f04a070cb2bd0ae9ed88660b Mon Sep 17 00:00:00 2001 From: Aidan Date: Wed, 10 Jun 2026 17:14:37 -0700 Subject: [PATCH] fix: stop dashboard select-mode from leaking onto other pages Dashboard stays mounted (visibility-hidden) behind every other route, so its ElementSelectionProvider and portal-rendered SelectionOverlay kept firing on top of the App Builder. Gate both the overlay render and the global mouse listeners in useDomElementSelector on useDashboardActive, leaving selection state untouched so it restores on return. --- frontend/src/app/components/editor/useDomElementSelector.ts | 6 ++++-- frontend/src/app/pages/Dashboard/Dashboard.tsx | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/editor/useDomElementSelector.ts b/frontend/src/app/components/editor/useDomElementSelector.ts index 6107e8b9..43eba97a 100644 --- a/frontend/src/app/components/editor/useDomElementSelector.ts +++ b/frontend/src/app/components/editor/useDomElementSelector.ts @@ -1,5 +1,6 @@ import { useEffect, useRef, useState, useCallback } from 'react'; import { SelectedElement, useElementSelection } from './ElementSelectionContext'; +import { useDashboardActive } from '@/shared/hooks/useDashboardActive'; const SELECT_ATTR = 'data-select-type'; const SELECT_ID_ATTR = 'data-select-id'; @@ -110,6 +111,7 @@ export interface DomSelectorState { export function useDomElementSelector(): DomSelectorState { const ctx = useElementSelection(); + const active = useDashboardActive(); const [overlay, setOverlay] = useState(EMPTY_OVERLAY); const [dragRect, setDragRect] = useState(EMPTY_DRAG); const [dragPreview, setDragPreview] = useState([]); @@ -330,7 +332,7 @@ export function useDomElementSelector(): DomSelectorState { }, [ctx]); useEffect(() => { - if (!ctx?.selectMode) { + if (!ctx?.selectMode || !active) { setOverlay(EMPTY_OVERLAY); setDragRect(EMPTY_DRAG); setDragPreview([]); @@ -369,7 +371,7 @@ export function useDomElementSelector(): DomSelectorState { // Defensive: if select mode flips off mid-drag, drop the class so webviews regain interactivity. document.body.classList.remove('dashboard-marquee-active'); }; - }, [ctx?.selectMode, handleMouseMove, handleMouseDown, handleMouseUp, handleClick]); + }, [ctx?.selectMode, active, handleMouseMove, handleMouseDown, handleMouseUp, handleClick]); return { overlay, dragRect, dragPreview }; } diff --git a/frontend/src/app/pages/Dashboard/Dashboard.tsx b/frontend/src/app/pages/Dashboard/Dashboard.tsx index 35b47bc2..d94cc0b9 100644 --- a/frontend/src/app/pages/Dashboard/Dashboard.tsx +++ b/frontend/src/app/pages/Dashboard/Dashboard.tsx @@ -2,11 +2,14 @@ import React from 'react'; import SelectionOverlay from '@/app/components/editor/SelectionOverlay'; import { ElementSelectionProvider } from '@/app/components/editor/ElementSelectionContext'; import { useDomElementSelector } from '@/app/components/editor/useDomElementSelector'; +import { useDashboardActive } from '@/shared/hooks/useDashboardActive'; import { useDashboardController } from './hooks/state/useDashboardController'; import DashboardCanvas from './canvas/DashboardCanvas'; const DashboardSelectionOverlay: React.FC = () => { + const active = useDashboardActive(); const { overlay, dragRect, dragPreview } = useDomElementSelector(); + if (!active) return null; return ; };