fix(web): let the pointer reach hover cards and row menus

The workspace browser's two hover-raised popups both died on the way to
them. HoverCard closed on the first pointerleave and rendered its card
pointer-events:none, but the card sits 8px off the anchor, so every path
to it crossed ground belonging to neither. The row action menus put
closeOnPointerLeave's handler on the portaled list, so aiming back at the
... trigger that opened it, or overshooting a list edge, closed it with no
window to come back.

usePointerGrace owns one cancelable delayed close (200ms) shared by both
atoms: leaving arms it, returning cancels it. The hover card becomes
hit-testable so resting on it holds it open, and Menu moves pointer-leave
dismissal to the wrapper span, where React's enter/leave traversal makes
trigger and portaled list one region.

Both gestures are pinned in the real browser lane; each fails without the
corresponding fix.
This commit is contained in:
creatixchu
2026-07-30 20:25:02 +08:00
parent 2e8c82634e
commit 2cac565383
10 files changed
+341 -38

No files matched your search

@@ -7,7 +7,9 @@
/* Preview card (figma session hover card): 244 wide, r12, pad 12/16, the
* menu card's elevation. Surface is #2C2C2E in both themes (figma value,
* light/dark identical), so a component-level variable, not a theme token. */
* light/dark identical), so a component-level variable, not a theme token.
* Hit-testable on purpose: resting the pointer on the card holds it open
* (HoverCard's grace close), which a `pointer-events: none` card cannot do. */
.card {
--dsw-hovercard-bg: #2C2C2E;
position: fixed;
@@ -18,5 +20,4 @@
border-radius: 12px;
background: var(--dsw-hovercard-bg);
box-shadow: var(--dsw-shadow-lv3);
pointer-events: none;
}