Skip to content

Commit

Permalink
fix(sidenav): not restoring focus to SVG elements (#18614)
Browse files Browse the repository at this point in the history
SVG nodes can be focusable, but they won't match `instanceof HTMLElement` so we never restore focus to them.

(cherry picked from commit 99d3e12)
  • Loading branch information
crisbeto authored and jelbourn committed Mar 3, 2020
1 parent c6e0fdf commit ed763f5
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/material/sidenav/drawer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,28 @@ describe('MatDrawer', () => {
.toBe(openButton, 'Expected focus to be restored to the open button on close.');
}));

it('should restore focus to an SVG element', fakeAsync(() => {
const fixture = TestBed.createComponent(BasicTestApp);
fixture.detectChanges();

const drawer = fixture.debugElement.query(By.directive(MatDrawer))!.componentInstance;
const svg = fixture.componentInstance.svg.nativeElement;
const drawerButton = fixture.componentInstance.drawerButton.nativeElement;

svg.focus();
drawer.open();
fixture.detectChanges();
flush();
drawerButton.focus();

drawer.close();
fixture.detectChanges();
flush();

expect(document.activeElement)
.toBe(svg, 'Expected focus to be restored to the SVG element on close.');
}));

it('should not restore focus on close if focus is outside drawer', fakeAsync(() => {
let fixture = TestBed.createComponent(BasicTestApp);
let drawer: MatDrawer = fixture.debugElement
Expand Down Expand Up @@ -907,6 +929,14 @@ class DrawerContainerTwoDrawerTestApp {
</mat-drawer>
<button (click)="drawer.open()" class="open" #openButton></button>
<button (click)="drawer.close()" class="close" #closeButton></button>
<svg
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
tabindex="0"
focusable="true"
#svg>
<circle cx="50" cy="50" r="50"/>
</svg>
</mat-drawer-container>`,
})
class BasicTestApp {
Expand All @@ -920,6 +950,7 @@ class BasicTestApp {
@ViewChild('drawer') drawer: MatDrawer;
@ViewChild('drawerButton') drawerButton: ElementRef<HTMLButtonElement>;
@ViewChild('openButton') openButton: ElementRef<HTMLButtonElement>;
@ViewChild('svg') svg: ElementRef<SVGElement>;
@ViewChild('closeButton') closeButton: ElementRef<HTMLButtonElement>;

open() {
Expand Down
3 changes: 2 additions & 1 deletion src/material/sidenav/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
const activeEl = this._doc && this._doc.activeElement;

if (activeEl && this._elementRef.nativeElement.contains(activeEl)) {
if (this._elementFocusedBeforeDrawerWasOpened instanceof HTMLElement) {
// Note that we don't check via `instanceof HTMLElement` so that we can cover SVGs as well.
if (this._elementFocusedBeforeDrawerWasOpened) {
this._focusMonitor.focusVia(this._elementFocusedBeforeDrawerWasOpened, this._openedVia);
} else {
this._elementRef.nativeElement.blur();
Expand Down

0 comments on commit ed763f5

Please sign in to comment.