Modals close on Escape, not just the X button
Docker / build-and-push (push) Successful in 1m42s

Characters modal was missing an Escape handler entirely (click-outside
already worked). Consolidated the Escape handling into one listener
that closes whichever overlay is topmost — lightbox first, then
characters, then help — so dismissing the lightbox with Escape doesn't
also close the characters modal underneath it.

Deliberately left the event-choice modal alone: that one represents a
decision with real game consequences, not just a "look at content"
overlay, so it should require an explicit choice rather than being
dismissible.

Verified via headless browser: Escape and click-outside both close
help, characters, and the lightbox correctly, with the lightbox/
characters layering behaving as expected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Fredrik Johansson
2026-08-01 22:23:42 +02:00
co-authored by Claude Sonnet 5
parent 3a741a7bfc
commit 666b64e748
+11 -2
View File
@@ -212,7 +212,7 @@ export function initUI(
document.getElementById('help-btn')!.addEventListener('click', () => helpModal.classList.toggle('visible'));
document.getElementById('help-close')!.addEventListener('click', () => helpModal.classList.remove('visible'));
helpModal.addEventListener('click', (e) => { if (!helpInner.contains(e.target as Node)) helpModal.classList.remove('visible'); });
document.addEventListener('keydown', (e) => { if (e.key === '?' || (e.key === 'Escape' && helpModal.classList.contains('visible'))) helpModal.classList.toggle('visible'); });
document.addEventListener('keydown', (e) => { if (e.key === '?') helpModal.classList.toggle('visible'); });
const charactersModal = document.getElementById('characters-modal')!;
const charactersInner = document.getElementById('characters-modal-inner')!;
@@ -252,7 +252,16 @@ export function initUI(
});
document.getElementById('lightbox-close')!.addEventListener('click', () => lightbox.classList.remove('visible'));
lightbox.addEventListener('click', (e) => { if (e.target === lightbox) lightbox.classList.remove('visible'); });
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') lightbox.classList.remove('visible'); });
// Escape closes whichever overlay is topmost — lightbox sits on top of
// the characters modal, which can sit on top of help, so check in that
// order and stop at the first one actually open.
document.addEventListener('keydown', (e) => {
if (e.key !== 'Escape') return;
if (lightbox.classList.contains('visible')) { lightbox.classList.remove('visible'); return; }
if (charactersModal.classList.contains('visible')) { charactersModal.classList.remove('visible'); return; }
if (helpModal.classList.contains('visible')) { helpModal.classList.remove('visible'); return; }
});
// Split the map container: map on top, log below
const mapContainer = document.getElementById('map-container')!;