From 6ca253591fa74b192abb714b9c2dbd9b93b379bb Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Mon, 22 Jun 2026 05:15:53 -0700 Subject: [PATCH] fix(dashboard): portal floating windows to body; board pop-out returns to board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FloatingWindow renders via createPortal(document.body) so it escapes every ancestor stacking context — card dependency/overlap badges and the List view's sticky sort header + column divider no longer paint over the modal (4000+ z-index now wins page-wide). - Popping out a task detail from the board's full-panel view also returns the main panel to the board, so the board sits behind the floating window. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/dashboard/app/App.tsx | 3 ++- packages/dashboard/app/components/FloatingWindow.tsx | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/dashboard/app/App.tsx b/packages/dashboard/app/App.tsx index 632645f2ec..b702bcb4db 100644 --- a/packages/dashboard/app/App.tsx +++ b/packages/dashboard/app/App.tsx @@ -2067,7 +2067,8 @@ function AppInner() { Board-card detail (full main panel) renders its "Back to board" affordance inside TaskDetailContent's gray header (far right, across from the task id) instead of a separate back-row above the content. The prop only renders the header back button when both embedded and onBackToBoard are present, so ListView split-pane and modal usages stay unaffected. */ onBackToBoard={closeTaskDetailMainPanel} - onPopOut={popOutTaskDetail} + /* FNXC:FloatingWindow 2026-06-22-21:10: Popping out from the board's full-panel detail also returns the main panel to the board, so the board (not the emptied detail) sits behind the floating window. */ + onPopOut={(task) => { popOutTaskDetail(task); closeTaskDetailMainPanel(); }} onOpenDetail={(value) => setMainPanelDetailTask(value)} onMoveTask={moveTask} onDeleteTask={deleteTask} diff --git a/packages/dashboard/app/components/FloatingWindow.tsx b/packages/dashboard/app/components/FloatingWindow.tsx index 67a531859e..5d4fe35940 100644 --- a/packages/dashboard/app/components/FloatingWindow.tsx +++ b/packages/dashboard/app/components/FloatingWindow.tsx @@ -7,6 +7,7 @@ import { type PointerEvent as ReactPointerEvent, type ReactNode, } from "react"; +import { createPortal } from "react-dom"; import { X } from "lucide-react"; import "./FloatingWindow.css"; @@ -268,7 +269,11 @@ export function FloatingWindow({ zIndex, } as CSSProperties; - return ( + /* + FNXC:FloatingWindow 2026-06-22-21:10: + Rendered via a portal to document.body so the window escapes every ancestor stacking context (board card badges, the List view's sticky sort header + column divider, transformed columns, etc.). Without the portal the panel's z-index battles inside whatever subtree mounted it, letting card dependency/overlap tags and the list divider/sort header paint over the modal. At document.body the 4000+ z-index wins over all page content. + */ + return createPortal(
- + , + document.body, ); }