mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(drawer): unable to close using keyboard if there are no focusable elements (#8783)
Fixes the drawer not trapping focus if it doesn't have any focusable elements, making it impossible to close using the keyboard.
This commit is contained in:
committed by
Andrew Seguin
parent
bd50fa6c36
commit
fba3728821
@@ -26,8 +26,9 @@ describe('MatDrawer', () => {
|
||||
DrawerSetToOpenedFalse,
|
||||
DrawerSetToOpenedTrue,
|
||||
DrawerDynamicPosition,
|
||||
DrawerWitFocusableElements,
|
||||
DrawerWithFocusableElements,
|
||||
DrawerOpenBinding,
|
||||
DrawerWithoutFocusableElements,
|
||||
],
|
||||
});
|
||||
|
||||
@@ -370,14 +371,14 @@ describe('MatDrawer', () => {
|
||||
});
|
||||
|
||||
describe('focus trapping behavior', () => {
|
||||
let fixture: ComponentFixture<DrawerWitFocusableElements>;
|
||||
let testComponent: DrawerWitFocusableElements;
|
||||
let fixture: ComponentFixture<DrawerWithFocusableElements>;
|
||||
let testComponent: DrawerWithFocusableElements;
|
||||
let drawer: MatDrawer;
|
||||
let firstFocusableElement: HTMLElement;
|
||||
let lastFocusableElement: HTMLElement;
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DrawerWitFocusableElements);
|
||||
fixture = TestBed.createComponent(DrawerWithFocusableElements);
|
||||
testComponent = fixture.debugElement.componentInstance;
|
||||
drawer = fixture.debugElement.query(By.directive(MatDrawer)).componentInstance;
|
||||
firstFocusableElement = fixture.debugElement.query(By.css('.link1')).nativeElement;
|
||||
@@ -417,6 +418,21 @@ describe('MatDrawer', () => {
|
||||
|
||||
expect(document.activeElement).toBe(lastFocusableElement);
|
||||
}));
|
||||
|
||||
it('should focus the drawer if there are no focusable elements', fakeAsync(() => {
|
||||
fixture.destroy();
|
||||
|
||||
const nonFocusableFixture = TestBed.createComponent(DrawerWithoutFocusableElements);
|
||||
const drawerEl = nonFocusableFixture.debugElement.query(By.directive(MatDrawer));
|
||||
nonFocusableFixture.detectChanges();
|
||||
|
||||
drawerEl.componentInstance.open();
|
||||
nonFocusableFixture.detectChanges();
|
||||
tick();
|
||||
|
||||
expect(document.activeElement).toBe(drawerEl.nativeElement);
|
||||
}));
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -676,10 +692,19 @@ class DrawerDynamicPosition {
|
||||
<a class="link2" href="#">link2</a>
|
||||
</mat-drawer-container>`,
|
||||
})
|
||||
class DrawerWitFocusableElements {
|
||||
class DrawerWithFocusableElements {
|
||||
mode: string = 'over';
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<mat-drawer-container>
|
||||
<mat-drawer position="start" mode="over">
|
||||
<button disabled>Not focusable</button>
|
||||
</mat-drawer>
|
||||
</mat-drawer-container>`,
|
||||
})
|
||||
class DrawerWithoutFocusableElements {}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
|
||||
@@ -261,6 +261,7 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
|
||||
private _focusMonitor: FocusMonitor,
|
||||
private _platform: Platform,
|
||||
@Optional() @Inject(DOCUMENT) private _doc: any) {
|
||||
|
||||
this.openedChange.subscribe((opened: boolean) => {
|
||||
if (opened) {
|
||||
if (this._doc) {
|
||||
@@ -268,7 +269,7 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
|
||||
}
|
||||
|
||||
if (this._isFocusTrapEnabled && this._focusTrap) {
|
||||
this._focusTrap.focusInitialElementWhenReady();
|
||||
this._trapFocus();
|
||||
}
|
||||
} else {
|
||||
this._restoreFocus();
|
||||
@@ -276,6 +277,17 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
|
||||
});
|
||||
}
|
||||
|
||||
/** Traps focus inside the drawer. */
|
||||
private _trapFocus() {
|
||||
this._focusTrap.focusInitialElementWhenReady().then(hasMovedFocus => {
|
||||
// If there were no focusable elements, focus the sidenav itself so the keyboard navigation
|
||||
// still works. We need to check that `focus` is a function due to Universal.
|
||||
if (!hasMovedFocus && typeof this._elementRef.nativeElement.focus === 'function') {
|
||||
this._elementRef.nativeElement.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* If focus is currently inside the drawer, restores it to where it was before the drawer
|
||||
* opened.
|
||||
|
||||
Reference in New Issue
Block a user