Skip to content

Commit 8d162d2

Browse files
committed
fix(modal): keep dialog focus on present with cycle handle
When a sheet modal defaults handleBehavior to "cycle" (the new default on major-9.0), the host becomes focusable and onModalFocus redirects focus to the drag handle. present() (from #31260) focuses the shadow-DOM dialog wrapper for screen readers, but that focus event is retargeted to the host at the shadow boundary, so onModalFocus saw ev.target === el and bounced focus onto the handle. The wrapper never kept focus, which failed the "focus the sheet modal wrapper on present" e2e on Firefox. Guard the redirect on el.shadowRoot.activeElement being null, which is true only when the host itself was focused directly (e.g. tabbing into the modal). When present() focuses the wrapper, activeElement is the wrapper, so the redirect is skipped and the dialog focus is left intact. Tabbing to the handle from outside still works.
1 parent cff35f5 commit 8d162d2

1 file changed

Lines changed: 10 additions & 2 deletions

File tree

core/src/components/modal/modal.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,8 +1188,16 @@ export class Modal implements ComponentInterface, OverlayInterface {
11881188
*/
11891189
private onModalFocus = (ev: FocusEvent) => {
11901190
const { dragHandleEl, el } = this;
1191-
// Only handle focus if the modal itself was focused (not a child element)
1192-
if (ev.target === el && dragHandleEl && dragHandleEl.tabIndex !== -1) {
1191+
/**
1192+
* Focus events from inside the shadow DOM are retargeted to the host, so
1193+
* `ev.target === el` is also true when a shadow child (e.g. the dialog
1194+
* wrapper that present() focuses for screen readers) receives focus. Use
1195+
* the shadow root's activeElement to tell the two apart: it is `null` only
1196+
* when the host itself was focused directly (e.g. tabbing into the modal).
1197+
* Only then do we redirect to the handle, so the wrapper focus set on
1198+
* present() is left intact.
1199+
*/
1200+
if (ev.target === el && el.shadowRoot?.activeElement == null && dragHandleEl && dragHandleEl.tabIndex !== -1) {
11931201
dragHandleEl.focus();
11941202
}
11951203
};

0 commit comments

Comments
 (0)