From 9863674a763960240222119d78c6a1904ffdabc1 Mon Sep 17 00:00:00 2001 From: amosblomqvist Date: Thu, 17 Sep 2026 18:33:59 +0300 Subject: [PATCH] fix: Electron drag mask resolves by DOM order, not z-index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The home header carried -webkit-app-region: drag after
in the tree, re-adding drag over the graph chrome row's no-drag carve-out — Electron's mask applies carve-outs only to regions added EARLIER in the DOM walk, so the gear/search/coverage/import buttons dragged the window. Fix: a dedicated 52px drag-mask div placed FIRST in the home page DOM; every carved control (chrome row, node detail card, toggle) comes later and subtracts correctly. The header loses its app-region entirely — the mask routes the pixels, the header stays a pure pointer-events container. Retires the .lh-float-drag CSS class. Verified live in the Electron dev shell by the owner: chrome row, sidebar close button, logo, and window drag all work. --- app/globals.css | 12 ++++-------- components/home.tsx | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/globals.css b/app/globals.css index 12b4b32..53558b0 100644 --- a/app/globals.css +++ b/app/globals.css @@ -313,15 +313,15 @@ body { in the plain browser — it keys off , which SidebarProvider sets after mount when it detects the Electron shell. - - .lh-drag window-drag region (must sit on pointer-receiving els) + - .lh-drag window-drag region — on a dedicated mask div in + home.tsx placed FIRST in the page DOM (the mask + resolves by DOM order, not z-index: no-drag subtracts + only regions added earlier in the tree) - .lh-no-drag carve-out for interactive elements inside a drag band - .lh-lights-gutter the sidebar LH band's traffic-light gutter: lights end at x≈68, the wordmark starts at 80px (5rem) - .lh-closed-toggle same gutter for the sidebar toggle when the sidebar is closed — the lights are static, the toggle moves - - .lh-float-drag the home header strip floats pointer-events-none over - the graph; only in Electron does it claim events and - become the drag surface for that page ───────────────────────────────────────────────────────────────────────── */ .lh-electron .lh-drag { -webkit-app-region: drag; @@ -337,7 +337,3 @@ body { .lh-electron .lh-closed-toggle { margin-left: 92px; } -.lh-electron .lh-float-drag { - pointer-events: auto; - -webkit-app-region: drag; -} diff --git a/components/home.tsx b/components/home.tsx index 4ea95de..e7a5c1e 100644 --- a/components/home.tsx +++ b/components/home.tsx @@ -51,6 +51,17 @@ export function Home() { return (
+ {/* Window-drag strip (merged chrome, owner 2026-09-17): a dedicated + mask element, deliberately FIRST in the DOM. Electron's app-region + mask resolves by DOM order — a no-drag element subtracts only drag + regions that came EARLIER in the tree — not by z-index, so the + header's old inline drag region (after
) re-added itself over + the graph chrome row's carve-out and the buttons dragged the window. + Placed first, every carved control (chrome row, node detail card, + the toggle) comes later and subtracts correctly. Pure mask: it + never needs to receive events — the mask routes the pixels. */} +
{/* Header floats over the graph — pointer-events-none except the - toggle, so the canvas stays draggable/hoverable around it. */} -
+ toggle, so the canvas stays draggable/hoverable around it. Carries + no app-region of its own: the strip's drag comes from the mask + div above, and the toggle's lh-no-drag subtracts from it (it is + later in the tree, so the subtraction sticks). */} +