From ee1b241e0a5f21b278f52158be4f1007b030b323 Mon Sep 17 00:00:00 2001 From: Kevinjohn Gallagher Date: Mon, 20 Jul 2026 01:46:15 +0100 Subject: [PATCH] Fix modal dispose scroll reset --- js/src/modal.js | 6 ++++++ js/tests/unit/modal.spec.js | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/js/src/modal.js b/js/src/modal.js index dd61649ecce0..df29016a552d 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -144,6 +144,12 @@ class Modal extends BaseComponent { EventHandler.off(window, EVENT_KEY) EventHandler.off(this._dialog, EVENT_KEY) + if (this._isShown) { + document.body.classList.remove(CLASS_NAME_OPEN) + this._resetAdjustments() + this._scrollBar.reset() + } + this._backdrop.dispose() this._focustrap.deactivate() diff --git a/js/tests/unit/modal.spec.js b/js/tests/unit/modal.spec.js index 2aa0b7655c14..08b22ec5f948 100644 --- a/js/tests/unit/modal.spec.js +++ b/js/tests/unit/modal.spec.js @@ -861,6 +861,27 @@ describe('Modal', () => { expect(spyOff).toHaveBeenCalledTimes(3) expect(spyDeactivate).toHaveBeenCalled() }) + + it('should reset scrollbars when disposing a shown modal', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + const spyReset = spyOn(ScrollBarHelper.prototype, 'reset').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + modal.dispose() + + expect(spyReset).toHaveBeenCalled() + expect(document.body).not.toHaveClass('modal-open') + expect(document.body.style.overflow).toEqual('') + resolve() + }) + + modal.show() + }) + }) }) describe('handleUpdate', () => {