Skip to content

Commit 9578006

Browse files
committed
fix(sidenav): not restoring focus to SVG elements
SVG nodes can be focusable, but they won't match `instanceof HTMLElement` so we never restore focus to them.
1 parent 1ba8b26 commit 9578006

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

src/material/sidenav/drawer.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,28 @@ describe('MatDrawer', () => {
307307
.toBe(openButton, 'Expected focus to be restored to the open button on close.');
308308
}));
309309

310+
it('should restore focus to an SVG element', fakeAsync(() => {
311+
const fixture = TestBed.createComponent(BasicTestApp);
312+
fixture.detectChanges();
313+
314+
const drawer = fixture.debugElement.query(By.directive(MatDrawer))!.componentInstance;
315+
const svg = fixture.componentInstance.svg.nativeElement;
316+
const drawerButton = fixture.componentInstance.drawerButton.nativeElement;
317+
318+
svg.focus();
319+
drawer.open();
320+
fixture.detectChanges();
321+
flush();
322+
drawerButton.focus();
323+
324+
drawer.close();
325+
fixture.detectChanges();
326+
flush();
327+
328+
expect(document.activeElement)
329+
.toBe(svg, 'Expected focus to be restored to the SVG element on close.');
330+
}));
331+
310332
it('should not restore focus on close if focus is outside drawer', fakeAsync(() => {
311333
let fixture = TestBed.createComponent(BasicTestApp);
312334
let drawer: MatDrawer = fixture.debugElement
@@ -907,6 +929,14 @@ class DrawerContainerTwoDrawerTestApp {
907929
</mat-drawer>
908930
<button (click)="drawer.open()" class="open" #openButton></button>
909931
<button (click)="drawer.close()" class="close" #closeButton></button>
932+
<svg
933+
viewBox="0 0 100 100"
934+
xmlns="http://www.w3.org/2000/svg"
935+
tabindex="0"
936+
focusable="true"
937+
#svg>
938+
<circle cx="50" cy="50" r="50"/>
939+
</svg>
910940
</mat-drawer-container>`,
911941
})
912942
class BasicTestApp {
@@ -920,6 +950,7 @@ class BasicTestApp {
920950
@ViewChild('drawer') drawer: MatDrawer;
921951
@ViewChild('drawerButton') drawerButton: ElementRef<HTMLButtonElement>;
922952
@ViewChild('openButton') openButton: ElementRef<HTMLButtonElement>;
953+
@ViewChild('svg') svg: ElementRef<SVGElement>;
923954
@ViewChild('closeButton') closeButton: ElementRef<HTMLButtonElement>;
924955

925956
open() {

src/material/sidenav/drawer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
350350
const activeEl = this._doc && this._doc.activeElement;
351351

352352
if (activeEl && this._elementRef.nativeElement.contains(activeEl)) {
353-
if (this._elementFocusedBeforeDrawerWasOpened instanceof HTMLElement) {
353+
// Note that we don't check via `instanceof HTMLElement` so that we can cover SVGs as well.
354+
if (this._elementFocusedBeforeDrawerWasOpened) {
354355
this._focusMonitor.focusVia(this._elementFocusedBeforeDrawerWasOpened, this._openedVia);
355356
} else {
356357
this._elementRef.nativeElement.blur();

0 commit comments

Comments
 (0)