diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts
index 7e2395d341..bf8192e59e 100644
--- a/core/src/utils/overlays.ts
+++ b/core/src/utils/overlays.ts
@@ -236,6 +236,41 @@ export const getOverlay = (doc: Document, overlayTag?: string, id?: string): HTM
: overlays.find(o => o.id === id);
};
+/**
+ * When an overlay is presented, the main
+ * focus is the overlay not the page content.
+ * We need to remove the page content from the
+ * accessibility tree otherwise when
+ * users use "read screen from top" gestures with
+ * TalkBack and VoiceOver, the screen reader will begin
+ * to read the content underneath the overlay.
+ *
+ * We need a container where all page components
+ * exist that is separate from where the overlays
+ * are added in the DOM. For most apps, this element
+ * is the top most ion-router-outlet. In the event
+ * that devs are not using a router,
+ * they will need to add the "ion-view-container-root"
+ * id to the element that contains all of their views.
+ *
+ * TODO: If Framework supports having multiple top
+ * level router outlets we would need to update this.
+ * Example: One outlet for side menu and one outlet
+ * for main content.
+ */
+export const setRootAriaHidden = (hidden = false) => {
+ const root = getAppRoot(document);
+ const viewContainer = root.querySelector('ion-router-outlet, ion-nav, #ion-view-container-root');
+
+ if (!viewContainer) { return; }
+
+ if (hidden) {
+ viewContainer.setAttribute('aria-hidden', 'true');
+ } else {
+ viewContainer.removeAttribute('aria-hidden');
+ }
+}
+
export const present = async (
overlay: OverlayInterface,
name: keyof IonicConfig,
@@ -246,6 +281,9 @@ export const present = async (
if (overlay.presented) {
return;
}
+
+ setRootAriaHidden(true);
+
overlay.presented = true;
overlay.willPresent.emit();
@@ -313,6 +351,9 @@ export const dismiss = async (
if (!overlay.presented) {
return false;
}
+
+ setRootAriaHidden(false);
+
overlay.presented = false;
try {
diff --git a/core/src/utils/test/overlays.spec.ts b/core/src/utils/test/overlays.spec.ts
new file mode 100644
index 0000000000..ec32ee9e94
--- /dev/null
+++ b/core/src/utils/test/overlays.spec.ts
@@ -0,0 +1,79 @@
+import { newSpecPage } from '@stencil/core/testing';
+import { setRootAriaHidden } from '../overlays';
+import { RouterOutlet } from '../../components/router-outlet/route-outlet';
+import { Nav } from '../../components/nav/nav';
+
+describe('setRootAriaHidden()', () => {
+ it('should correctly remove and re-add router outlet from accessibility tree', async () => {
+ const page = await newSpecPage({
+ components: [RouterOutlet],
+ html: `
+