diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts index 90a4062840e..a6e3fed3260 100644 --- a/core/src/utils/overlays.ts +++ b/core/src/utils/overlays.ts @@ -646,6 +646,14 @@ export const dismiss = async ( return false; } + const presentedOverlays = doc !== undefined ? getPresentedOverlays(doc) : []; + + const isLastOverlay = presentedOverlays.length === 1; + + if (isLastOverlay) { + document.body.classList.remove(BACKDROP_NO_SCROLL); + } + /** * For accessibility, toasts lack focus traps and don’t receive * `aria-hidden` on the root element when presented. @@ -657,7 +665,7 @@ export const dismiss = async ( * Therefore, we must remove `aria-hidden` from the root element * when the last non-toast overlay is dismissed. */ - const overlaysNotToast = doc !== undefined ? getPresentedOverlays(doc).filter((o) => o.tagName !== 'ION-TOAST') : []; + const overlaysNotToast = presentedOverlays.filter((o) => o.tagName !== 'ION-TOAST'); const lastOverlayNotToast = overlaysNotToast.length === 1 && overlaysNotToast[0].id === overlay.el.id; @@ -667,7 +675,6 @@ export const dismiss = async ( */ if (lastOverlayNotToast) { setRootAriaHidden(false); - document.body.classList.remove(BACKDROP_NO_SCROLL); } overlay.presented = false; diff --git a/core/src/utils/test/overlays/overlays-scroll-blocking.spec.ts b/core/src/utils/test/overlays/overlays-scroll-blocking.spec.ts index 2fcafadd9fd..e4aca09cdf4 100644 --- a/core/src/utils/test/overlays/overlays-scroll-blocking.spec.ts +++ b/core/src/utils/test/overlays/overlays-scroll-blocking.spec.ts @@ -1,6 +1,7 @@ import { newSpecPage } from '@stencil/core/testing'; import { Modal } from '../../../components/modal/modal'; +import { Toast } from '../../../components/toast/toast'; describe('overlays: scroll blocking', () => { it('should not block scroll when the overlay is created', async () => { @@ -85,4 +86,34 @@ describe('overlays: scroll blocking', () => { expect(body).not.toHaveClass('backdrop-no-scroll'); }); + + it('should not enable scroll until last toast overlay is dismissed', async () => { + const page = await newSpecPage({ + components: [Toast], + html: ` + + + `, + }); + + const toastOne = page.body.querySelector('#one') as HTMLIonToastElement; + const toastTwo = page.body.querySelector('#two') as HTMLIonToastElement; + const body = page.doc.querySelector('body')!; + + await toastOne.present(); + + expect(body).toHaveClass('backdrop-no-scroll'); + + await toastTwo.present(); + + expect(body).toHaveClass('backdrop-no-scroll'); + + await toastOne.dismiss(); + + expect(body).toHaveClass('backdrop-no-scroll'); + + await toastTwo.dismiss(); + + expect(body).not.toHaveClass('backdrop-no-scroll'); + }); });