Skip to content

Commit 5ddc39c

Browse files
committed
fix(overlays): only retarget focus to a focusable dialog wrapper
present() queried the overlay for `[role="dialog"]`, but picker-legacy puts that role on a wrapper with no tabindex. Focusing a non-focusable element is a no-op, so focus would not move into the picker (a regression from focusing the host). Qualify the query with `[tabindex]` so only a focusable dialog wrapper (e.g. the modal wrapper) is targeted; otherwise fall back to the host, preserving prior behavior.
1 parent b0b5256 commit 5ddc39c

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

core/src/utils/overlays.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,9 +597,12 @@ export const present = async <OverlayPresentOptions>(
597597
* Some overlays (e.g. modal) put the dialog role and label on the
598598
* `.ion-overlay-wrapper` rather than the host. Screen readers need
599599
* focus on the element with role="dialog" to properly announce and
600-
* navigate the dialog.
600+
* navigate the dialog. The `[tabindex]` qualifier ensures we only
601+
* target such a wrapper when it is actually focusable; otherwise
602+
* (e.g. picker-legacy, whose role="dialog" wrapper has no tabindex)
603+
* `focus()` would be a no-op, so we fall back to the host.
601604
*/
602-
const overlayWrapper = getElementRoot(overlay.el).querySelector<HTMLElement>('[role="dialog"]');
605+
const overlayWrapper = getElementRoot(overlay.el).querySelector<HTMLElement>('[role="dialog"][tabindex]');
603606
const focusTarget = overlayWrapper ?? overlay.el;
604607
focusTarget.focus({ preventScroll: true });
605608
}

0 commit comments

Comments
 (0)