fix: themed-dialog click-to-dismiss fires on any shadow-internal click, not just the backdrop

hive-dialog's dismiss-on-backdrop-click handler checked e.target === this
(the host). Shadow DOM event retargeting sets e.target to the host for
ANY click that originated inside the shadow tree once it reaches a
listener attached on the host itself, not just clicks that actually hit
the host's own rendering — so the check was true for every click inside
.box that no other element's listener consumed first (title, message, a
bare checkbox row with no button to intercept it), immediately closing
the whole dialog. Reported by mara: clicking a checkbox in a
confirmation dialog (e.g. the restart dialog) dismissed the dialog
instead of toggling the box.

Switched to e.composedPath()[0] === this, the true original target
unaffected by retargeting — true only for a genuine backdrop click.
This commit is contained in:
iris 2026-07-31 21:33:33 +02:00
commit e9a1764f42

View file

@ -105,7 +105,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);