From a0bb1a36bb4bcc08e2abe9b6eae84a9be0887bb8 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 12 Oct 2017 21:38:29 +0200 Subject: [PATCH] fix(button): focus styles not applied to programmatically focused buttons (#5966) Currently the tint that is added on top of focused buttons won't show up if the button is focused programmatically, which means that the button won't appear focused in cases like the dialog closing and restoring focus to its trigger. This seems to have been introduced by 5d6920dde6cbe17f2888b7e09f123e02db251b0f. Fixes #7510. --- src/demo-app/button/button-demo.html | 7 +++--- src/demo-app/demo-app/demo-app.html | 2 +- src/demo-app/sidenav/sidenav-demo.html | 10 ++++---- src/lib/button-toggle/button-toggle.scss | 9 ++++--- src/lib/button/_button-base.scss | 2 +- src/lib/datepicker/_datepicker-theme.scss | 3 ++- src/lib/sidenav/drawer.ts | 30 +++++++++++++++++------ src/lib/slider/slider.scss | 3 ++- 8 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/demo-app/button/button-demo.html b/src/demo-app/button/button-demo.html index 2b3400b1576..211d2c0c33b 100644 --- a/src/demo-app/button/button-demo.html +++ b/src/demo-app/button/button-demo.html @@ -73,11 +73,12 @@ + - - off - + + off + diff --git a/src/demo-app/demo-app/demo-app.html b/src/demo-app/demo-app/demo-app.html index cb6e9d90453..ba6af65434b 100644 --- a/src/demo-app/demo-app/demo-app.html +++ b/src/demo-app/demo-app/demo-app.html @@ -24,7 +24,7 @@
-
diff --git a/src/demo-app/sidenav/sidenav-demo.html b/src/demo-app/sidenav/sidenav-demo.html index 31de4f40dd7..728a85dacd4 100644 --- a/src/demo-app/sidenav/sidenav-demo.html +++ b/src/demo-app/sidenav/sidenav-demo.html @@ -9,9 +9,9 @@ [fixedInViewport]="fixed" [fixedTopGap]="fixedTop" [fixedBottomGap]="fixedBottom"> Start Side Sidenav
- +
- +
Mode: {{start.mode}}
@@ -24,7 +24,7 @@ [fixedInViewport]="fixed" [fixedTopGap]="fixedTop" [fixedBottomGap]="fixedBottom"> End Side Sidenav
- +
Filler Content
@@ -39,8 +39,8 @@

Sidenav

- - + + Fixed mode Sidenav covers header/footer
diff --git a/src/lib/button-toggle/button-toggle.scss b/src/lib/button-toggle/button-toggle.scss index ea408e5505b..89c58c62880 100644 --- a/src/lib/button-toggle/button-toggle.scss +++ b/src/lib/button-toggle/button-toggle.scss @@ -38,10 +38,13 @@ $mat-button-toggle-border-radius: 2px !default; .mat-button-toggle { white-space: nowrap; position: relative; -} -.mat-button-toggle.cdk-keyboard-focused .mat-button-toggle-focus-overlay { - opacity: 1; + &.cdk-keyboard-focused, + &.cdk-program-focused { + .mat-button-toggle-focus-overlay { + opacity: 1; + } + } } .mat-button-toggle-label-content { diff --git a/src/lib/button/_button-base.scss b/src/lib/button/_button-base.scss index 44b9e39e3aa..e3606174d34 100644 --- a/src/lib/button/_button-base.scss +++ b/src/lib/button/_button-base.scss @@ -51,7 +51,7 @@ $mat-mini-fab-padding: 8px !default; cursor: default; } - &.cdk-keyboard-focused { + &.cdk-keyboard-focused, &.cdk-program-focused { .mat-button-focus-overlay { opacity: 1; } diff --git a/src/lib/datepicker/_datepicker-theme.scss b/src/lib/datepicker/_datepicker-theme.scss index 729adf43fb1..f1a48d7bf71 100644 --- a/src/lib/datepicker/_datepicker-theme.scss +++ b/src/lib/datepicker/_datepicker-theme.scss @@ -52,7 +52,8 @@ $mat-calendar-weekday-table-font-size: 11px !default; } :not(.mat-calendar-body-disabled):hover, - .cdk-keyboard-focused .mat-calendar-body-active { + .cdk-keyboard-focused .mat-calendar-body-active, + .cdk-program-focused .mat-calendar-body-active { & > .mat-calendar-body-cell-content:not(.mat-calendar-body-selected) { background-color: mat-color($background, hover); } diff --git a/src/lib/sidenav/drawer.ts b/src/lib/sidenav/drawer.ts index 51193b112e3..464afbe4254 100644 --- a/src/lib/sidenav/drawer.ts +++ b/src/lib/sidenav/drawer.ts @@ -7,7 +7,7 @@ */ import {animate, AnimationEvent, state, style, transition, trigger} from '@angular/animations'; -import {FocusTrap, FocusTrapFactory} from '@angular/cdk/a11y'; +import {FocusTrap, FocusTrapFactory, FocusMonitor, FocusOrigin} from '@angular/cdk/a11y'; import {Directionality} from '@angular/cdk/bidi'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; import {ESCAPE} from '@angular/cdk/keycodes'; @@ -172,6 +172,9 @@ export class MatDrawer implements AfterContentInit, OnDestroy { /** Whether the drawer is opened. */ private _opened: boolean = false; + /** How the sidenav was opened (keypress, mouse click etc.) */ + private _openedVia: FocusOrigin | null; + /** Emits whenever the drawer has started animating. */ _animationStarted = new EventEmitter(); @@ -230,6 +233,7 @@ export class MatDrawer implements AfterContentInit, OnDestroy { constructor(private _elementRef: ElementRef, private _focusTrapFactory: FocusTrapFactory, + private _focusMonitor: FocusMonitor, @Optional() @Inject(DOCUMENT) private _doc: any) { this.openedChange.subscribe((opened: boolean) => { if (opened) { @@ -251,16 +255,18 @@ export class MatDrawer implements AfterContentInit, OnDestroy { * opened. */ private _restoreFocus() { - let activeEl = this._doc && this._doc.activeElement; + const activeEl = this._doc && this._doc.activeElement; + if (activeEl && this._elementRef.nativeElement.contains(activeEl)) { if (this._elementFocusedBeforeDrawerWasOpened instanceof HTMLElement) { - this._elementFocusedBeforeDrawerWasOpened.focus(); + this._focusMonitor.focusVia(this._elementFocusedBeforeDrawerWasOpened, this._openedVia); } else { this._elementRef.nativeElement.blur(); } } this._elementFocusedBeforeDrawerWasOpened = null; + this._openedVia = null; } ngAfterContentInit() { @@ -285,10 +291,13 @@ export class MatDrawer implements AfterContentInit, OnDestroy { this.toggle(coerceBooleanProperty(v)); } - - /** Open the drawer. */ - open(): Promise { - return this.toggle(true); + /** + * Open the drawer. + * @param openedVia Whether the drawer was opened by a key press, mouse click or programmatically. + * Used for focus management after the sidenav is closed. + */ + open(openedVia?: FocusOrigin): Promise { + return this.toggle(true, openedVia); } /** Close the drawer. */ @@ -299,12 +308,17 @@ export class MatDrawer implements AfterContentInit, OnDestroy { /** * Toggle this drawer. * @param isOpen Whether the drawer should be open. + * @param openedVia Whether the drawer was opened by a key press, mouse click or programmatically. + * Used for focus management after the sidenav is closed. */ - toggle(isOpen: boolean = !this.opened): Promise { + toggle(isOpen: boolean = !this.opened, openedVia: FocusOrigin = 'program'): + Promise { + this._opened = isOpen; if (isOpen) { this._animationState = this._enableAnimations ? 'open' : 'open-instant'; + this._openedVia = openedVia; } else { this._animationState = 'void'; this._restoreFocus(); diff --git a/src/lib/slider/slider.scss b/src/lib/slider/slider.scss index f27f052bd1b..edcf83304b8 100644 --- a/src/lib/slider/slider.scss +++ b/src/lib/slider/slider.scss @@ -93,7 +93,8 @@ $mat-slider-focus-ring-size: 30px !default; background-color $swift-ease-out-duration $swift-ease-out-timing-function, opacity $swift-ease-out-duration $swift-ease-out-timing-function; - .cdk-keyboard-focused & { + .cdk-keyboard-focused &, + .cdk-program-focused & { transform: scale(1); opacity: 1; }