diff --git a/src/material/sidenav/drawer.ts b/src/material/sidenav/drawer.ts index 90776445316e..c3bfd8260e3b 100644 --- a/src/material/sidenav/drawer.ts +++ b/src/material/sidenav/drawer.ts @@ -296,7 +296,7 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr this._takeFocus(); } else if (this._isFocusWithinDrawer()) { - this._restoreFocus(); + this._restoreFocus(this._openedVia || 'program'); } }); @@ -400,20 +400,18 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr * Restores focus to the element that was originally focused when the drawer opened. * If no element was focused at that time, the focus will be restored to the drawer. */ - private _restoreFocus() { + private _restoreFocus(focusOrigin: Exclude) { if (this.autoFocus === 'dialog') { return; } - // 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); + this._focusMonitor.focusVia(this._elementFocusedBeforeDrawerWasOpened, focusOrigin); } else { this._elementRef.nativeElement.blur(); } this._elementFocusedBeforeDrawerWasOpened = null; - this._openedVia = null; } /** Whether focus is currently within the drawer. */ @@ -467,8 +465,8 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr _closeViaBackdropClick(): Promise { // If the drawer is closed upon a backdrop click, we always want to restore focus. We // don't need to check whether focus is currently in the drawer, as clicking on the - // backdrop causes blurring of the active element. - return this._setOpen(/* isOpen */ false, /* restoreFocus */ true); + // backdrop causes blurs the active element. + return this._setOpen(/* isOpen */ false, /* restoreFocus */ true, 'mouse'); } /** @@ -481,28 +479,36 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr : Promise { // If the focus is currently inside the drawer content and we are closing the drawer, // restore the focus to the initially focused element (when the drawer opened). - return this._setOpen( - isOpen, /* restoreFocus */ !isOpen && this._isFocusWithinDrawer(), openedVia); + if (isOpen && openedVia) { + this._openedVia = openedVia; + } + + const result = this._setOpen(isOpen, /* restoreFocus */ !isOpen && this._isFocusWithinDrawer(), + this._openedVia || 'program'); + + if (!isOpen) { + this._openedVia = null; + } + + return result; } /** * Toggles the opened state of the drawer. * @param isOpen Whether the drawer should open or close. * @param restoreFocus Whether focus should be restored on close. - * @param openedVia Focus origin that can be optionally set when opening a drawer. The - * origin will be used later when focus is restored on drawer close. + * @param focusOrigin Origin to use when restoring focus. */ - private _setOpen(isOpen: boolean, restoreFocus: boolean, openedVia: FocusOrigin = 'program') - : Promise { + private _setOpen(isOpen: boolean, restoreFocus: boolean, focusOrigin: Exclude): + Promise { this._opened = isOpen; if (isOpen) { this._animationState = this._enableAnimations ? 'open' : 'open-instant'; - this._openedVia = openedVia; } else { this._animationState = 'void'; if (restoreFocus) { - this._restoreFocus(); + this._restoreFocus(focusOrigin); } }