fix: Esc priority across slideover / settings / modal handlers

Pressing Esc after editing a card silently failed: requestCloseSlideOver
opened the discard-confirm modal, then the global Esc-fallback handler
fired on the same keystroke and either closed the just-opened modal
(when Esc came on a clean slideover via the modal path) or, when
Settings was layered on top of a dirty slideover, opened the discard
prompt in the background while Settings closed.

Both panel-level Esc handlers now run in capture phase and
stopPropagation:
- Slideover handler stops only when it actually acts (slideover open,
  no modal up, Settings not on top) so a single Esc opens the discard
  confirm without the global fallback racing to close it.
- Settings handler stops when Settings is the active panel so the
  global fallback's requestCloseSlideOver branch can't fire underneath
  and pop a discard confirm on the slideover the user left dirty.

Priority order is now: open modal > Settings > slideover. First Esc on
"card dirty + Settings open" closes Settings; second Esc shows the
discard confirm. Clean slideover + Esc still closes directly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-06-30 23:45:17 +01:00
parent bd14831449
commit 4cb45ec63a
2 changed files with 18 additions and 1 deletions
+18 -1
View File
@@ -10402,6 +10402,18 @@ async function init() {
if (e.key !== 'Escape') return;
if (!$('#slideover').classList.contains('is-open')) return;
if (document.querySelector('.modal:not(.is-hidden)')) return;
// Settings panel takes priority — when both Settings AND the
// editor are open, the first Esc should close Settings (the
// thing the user just opened on top), the second Esc handles
// the editor's dirty-check. Let the Settings Esc handler run.
if ($('#settingsPanel').classList.contains('is-open')) return;
// Stop here so the global "Esc closes confirmModal" handler
// doesn't fire on the SAME keystroke and immediately dismiss
// the discard-confirm dialog that requestCloseSlideOver just
// opened — that bug left the user with no visible feedback at
// all (modal opened and closed in one tick).
e.preventDefault();
e.stopPropagation();
requestCloseSlideOver();
}, true);
// Click-outside closes too. mousedown origin is captured so a
@@ -10585,8 +10597,13 @@ async function init() {
if (e.key !== 'Escape') return;
if (!$('#settingsPanel').classList.contains('is-open')) return;
if (document.querySelector('.modal:not(.is-hidden)')) return;
// Don't let the global Esc-fallback handler fire on the same
// keystroke — its slideover-close branch would pop the discard
// confirm in the background while Settings closes, surprising
// the user who expected one Esc = close one panel.
e.stopPropagation();
closeSettings();
});
}, true);
// Settings search box: live filter on every input. Escape clears the
// query (without closing the panel — the existing Esc handler also