diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts index 60da898cfe..48be57b788 100644 --- a/core/src/utils/overlays.ts +++ b/core/src/utils/overlays.ts @@ -430,7 +430,13 @@ export const present = async ( focusPreviousElementOnDismiss(overlay.el); } - if (overlay.keyboardClose) { + /** + * If the focused element is already + * inside the overlay component then + * focus should not be moved from that + * to the overlay container. + */ + if (overlay.keyboardClose && (document.activeElement === null || !overlay.el.contains(document.activeElement))) { overlay.el.focus(); } }; diff --git a/core/src/utils/test/overlays/overlays.e2e.ts b/core/src/utils/test/overlays/overlays.e2e.ts new file mode 100644 index 0000000000..a6eefce4c2 --- /dev/null +++ b/core/src/utils/test/overlays/overlays.e2e.ts @@ -0,0 +1,29 @@ +import { expect } from '@playwright/test'; +import { test } from '@utils/test/playwright'; + +test.describe('overlays: focus', () => { + test('should not focus the overlay container if element inside of overlay is focused', async ({ page }, testInfo) => { + test.skip(testInfo.project.metadata.rtl === true, 'RTL tests are not needed as layout is not checked'); + + await page.setContent(` + Show Modal + + + + + + `); + + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const button = page.locator('ion-button'); + const input = page.locator('ion-input'); + + await button.click(); + await input.evaluate((el: HTMLIonInputElement) => el.setFocus()); + + await ionModalDidPresent.next(); + await page.waitForChanges(); + + expect(page.locator('ion-input input')).toBeFocused(); + }); +});