From 94390da54ce3da30870ecea3eaa230effa79d4f6 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 31 Jul 2026 21:37:39 +0200 Subject: [PATCH] rebase: port hyperhive#2874's composedPath() click-retarget fix into hive-dialog.js #2875 (merged) fixed this on main's flat modal.js before #2793's component-dir split landed. Porting the same one-line fix here now instead of leaving it as a rebase landmine for whichever PR merges second. --- .../packages/shared/src/hive-dialog/hive-dialog.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/frontend/packages/shared/src/hive-dialog/hive-dialog.js b/frontend/packages/shared/src/hive-dialog/hive-dialog.js index 790b2ba3..ffea1a4a 100644 --- a/frontend/packages/shared/src/hive-dialog/hive-dialog.js +++ b/frontend/packages/shared/src/hive-dialog/hive-dialog.js @@ -80,7 +80,19 @@ class HiveDialog extends HTMLElement { root.append(box); this.addEventListener('click', (e) => { - if (dismissable && e.target === this) done(null); + // `e.target` is retargeted to `this` (the host) for ANY click that + // originated inside the shadow tree, once it bubbles out to a + // listener attached on the host itself — per spec, retargeting + // applies to every ancestor outside the shadow tree, and the host + // element's own light-DOM-side listeners count as outside. So + // `e.target === this` was true for every click inside `.box` too + // (title, message, a bare checkbox row with no button to consume + // it first), not just genuine backdrop clicks — dismissing the + // whole dialog on, say, a checkbox click. + // `composedPath()[0]` is the true original target, unaffected by + // retargeting: it's `this` only when nothing inside the shadow + // tree was actually under the cursor, i.e. a real backdrop click. + if (dismissable && e.composedPath()[0] === this) done(null); }); document.addEventListener('keydown', onKey, true);