mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-02 18:10:18 +05:30
fix: resolve modal stacking, animation, and close cleanup bugs
- Set backdrop z-index:0 and content z-index:1 to fix backdrop covering modal content within the stacking context - Force reflow between removing hidden and adding open class so CSS opacity transition fires correctly - Add transitionend listener + setTimeout fallback to restore hidden class after close animation completes - Override flex:1 on modal footer buttons to prevent full-width stretch - Add min-width to modal size variants for consistent sizing - Add 23 tests covering open/close lifecycle, keyboard, and destroy Amit Haridas
This commit is contained in:
@@ -124,8 +124,12 @@ class ModalManager {
|
||||
// Track open modals
|
||||
ModalManager.#openModals.push(this);
|
||||
|
||||
// Show modal (remove hidden, add open)
|
||||
// Show modal: remove hidden first, force a reflow so the browser
|
||||
// records opacity:0 as the start state, then add 'open' to trigger
|
||||
// the CSS transition. Without the reflow, both class changes are
|
||||
// batched into one style recalculation and the transition is skipped.
|
||||
this.#modal.classList.remove('hidden');
|
||||
void this.#modal.offsetHeight; // Force reflow — do not remove
|
||||
this.#modal.classList.add('open');
|
||||
this.#isOpen = true;
|
||||
|
||||
@@ -165,10 +169,28 @@ class ModalManager {
|
||||
ModalManager.#openModals.splice(index, 1);
|
||||
}
|
||||
|
||||
// Hide modal
|
||||
// Start hide transition
|
||||
this.#modal.classList.remove('open');
|
||||
this.#isOpen = false;
|
||||
|
||||
// Re-add 'hidden' after the CSS transition completes so the modal
|
||||
// is fully removed from rendering (display:none), not just invisible.
|
||||
// We use both transitionend and a setTimeout fallback because
|
||||
// transitionend never fires when prefers-reduced-motion disables transitions.
|
||||
let hidden = false;
|
||||
const addHidden = () => {
|
||||
if (hidden || this.#isOpen) return;
|
||||
hidden = true;
|
||||
this.#modal.removeEventListener('transitionend', onTransitionEnd);
|
||||
this.#modal.classList.add('hidden');
|
||||
};
|
||||
const onTransitionEnd = (e) => {
|
||||
if (e.target !== this.#modal) return;
|
||||
addHidden();
|
||||
};
|
||||
this.#modal.addEventListener('transitionend', onTransitionEnd);
|
||||
setTimeout(addHidden, 250); // fallback: slightly longer than 200ms transition
|
||||
|
||||
// Restore body scroll if no modals open
|
||||
if (ModalManager.#openModals.length === 0) {
|
||||
document.body.style.overflow = '';
|
||||
|
||||
Reference in New Issue
Block a user