Skip to content

Commit ab25c71

Browse files
committed
fix(toast): remove backdrop-no-scroll for last toast overlay
In case last overlay is a toast, the backdrop-no-scroll css class is removed from body. closes #30112
1 parent 05928e3 commit ab25c71

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

core/src/utils/overlays.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,14 @@ export const dismiss = async <OverlayDismissOptions>(
646646
return false;
647647
}
648648

649+
const presentedOverlays = doc !== undefined ? getPresentedOverlays(doc) : [];
650+
651+
const isLastOverlay = presentedOverlays.length === 1;
652+
653+
if (isLastOverlay) {
654+
document.body.classList.remove(BACKDROP_NO_SCROLL);
655+
}
656+
649657
/**
650658
* For accessibility, toasts lack focus traps and don’t receive
651659
* `aria-hidden` on the root element when presented.
@@ -657,7 +665,7 @@ export const dismiss = async <OverlayDismissOptions>(
657665
* Therefore, we must remove `aria-hidden` from the root element
658666
* when the last non-toast overlay is dismissed.
659667
*/
660-
const overlaysNotToast = doc !== undefined ? getPresentedOverlays(doc).filter((o) => o.tagName !== 'ION-TOAST') : [];
668+
const overlaysNotToast = presentedOverlays.filter((o) => o.tagName !== 'ION-TOAST');
661669

662670
const lastOverlayNotToast = overlaysNotToast.length === 1 && overlaysNotToast[0].id === overlay.el.id;
663671

@@ -667,7 +675,6 @@ export const dismiss = async <OverlayDismissOptions>(
667675
*/
668676
if (lastOverlayNotToast) {
669677
setRootAriaHidden(false);
670-
document.body.classList.remove(BACKDROP_NO_SCROLL);
671678
}
672679

673680
overlay.presented = false;

core/src/utils/test/overlays/overlays-scroll-blocking.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { newSpecPage } from '@stencil/core/testing';
22

33
import { Modal } from '../../../components/modal/modal';
4+
import { Toast } from '../../../components/toast/toast';
45

56
describe('overlays: scroll blocking', () => {
67
it('should not block scroll when the overlay is created', async () => {
@@ -85,4 +86,34 @@ describe('overlays: scroll blocking', () => {
8586

8687
expect(body).not.toHaveClass('backdrop-no-scroll');
8788
});
89+
90+
it('should not enable scroll until last toast overlay is dismissed', async () => {
91+
const page = await newSpecPage({
92+
components: [Toast],
93+
html: `
94+
<ion-toast id="one"></ion-toast>
95+
<ion-toast id="two"></ion-toast>
96+
`,
97+
});
98+
99+
const toastOne = page.body.querySelector('#one') as HTMLIonToastElement;
100+
const toastTwo = page.body.querySelector('#two') as HTMLIonToastElement;
101+
const body = page.doc.querySelector('body')!;
102+
103+
await toastOne.present();
104+
105+
expect(body).toHaveClass('backdrop-no-scroll');
106+
107+
await toastTwo.present();
108+
109+
expect(body).toHaveClass('backdrop-no-scroll');
110+
111+
await toastOne.dismiss();
112+
113+
expect(body).toHaveClass('backdrop-no-scroll');
114+
115+
await toastTwo.dismiss();
116+
117+
expect(body).not.toHaveClass('backdrop-no-scroll');
118+
});
88119
});

0 commit comments

Comments
 (0)