Skip to content

Commit

Permalink
fix(material/menu): debugging focusing the first item with iOS Voiceover
Browse files Browse the repository at this point in the history
  • Loading branch information
zarend committed Apr 4, 2022
1 parent 26e6c1f commit 06fa24d
Showing 1 changed file with 22 additions and 20 deletions.
42 changes: 22 additions & 20 deletions src/material/menu/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,29 +404,31 @@ export class _MatMenuBase
* out so we don't repeat the same logic in the public `focusFirstItem` method.
*/
private _focusFirstItem(origin: FocusOrigin) {
const manager = this._keyManager;
setTimeout(() => {
const manager = this._keyManager;

manager.setFocusOrigin(origin).setFirstItemActive();

// If there's no active item at this point, it means that all the items are disabled.
// Move focus to the menu panel so keyboard events like Escape still work. Also this will
// give _some_ feedback to screen readers.
if (!manager.activeItem && this._directDescendantItems.length) {
let element = this._directDescendantItems.first!._getHostElement().parentElement;

// Because the `mat-menu` is at the DOM insertion point, not inside the overlay, we don't
// have a nice way of getting a hold of the menu panel. We can't use a `ViewChild` either
// because the panel is inside an `ng-template`. We work around it by starting from one of
// the items and walking up the DOM.
while (element) {
if (element.getAttribute('role') === 'menu') {
element.focus();
break;
} else {
element = element.parentElement;
manager.setFocusOrigin(origin).setFirstItemActive();

// If there's no active item at this point, it means that all the items are disabled.
// Move focus to the menu panel so keyboard events like Escape still work. Also this will
// give _some_ feedback to screen readers.
if (!manager.activeItem && this._directDescendantItems.length) {
let element = this._directDescendantItems.first!._getHostElement().parentElement;

// Because the `mat-menu` is at the DOM insertion point, not inside the overlay, we don't
// have a nice way of getting a hold of the menu panel. We can't use a `ViewChild` either
// because the panel is inside an `ng-template`. We work around it by starting from one of
// the items and walking up the DOM.
while (element) {
if (element.getAttribute('role') === 'menu') {
console.log('MatMenu focusing on', element);
break;
} else {
element = element.parentElement;
}
}
}
}
}, 0);
}

/**
Expand Down

0 comments on commit 06fa24d

Please sign in to comment.