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 5d6920dde6.

Fixes #7510.
This commit is contained in:
Kristiyan Kostadinov
2017-10-12 21:38:29 +02:00
committed by Andrew Seguin
parent 70c349c23f
commit a0bb1a36bb
8 changed files with 43 additions and 23 deletions
+4 -3
View File
@@ -73,11 +73,12 @@
<button mat-raised-button (click)="button1.focus()">Focus 1</button>
<button mat-raised-button (click)="button2.focus()">Focus 2</button>
<button mat-raised-button (click)="button3.focus()">Focus 3</button>
<button mat-raised-button (click)="button4.focus()">Focus 4</button>
</div>
<button mat-button #button1 [disabled]="isDisabled" (click)="clickCounter=clickCounter+1">off</button>
<button mat-button color="primary" [disabled]="isDisabled">off</button>
<a href="http://www.google.com" #button2 mat-button color="accent" [disabled]="isDisabled">off</a>
<button mat-raised-button #button3 color="primary" [disabled]="isDisabled">off</button>
<button mat-button #button2 color="primary" [disabled]="isDisabled">off</button>
<a href="http://www.google.com" #button3 mat-button color="accent" [disabled]="isDisabled">off</a>
<button mat-raised-button #button4 color="primary" [disabled]="isDisabled">off</button>
<button mat-mini-fab [disabled]="isDisabled">
<mat-icon>check</mat-icon>
</button>
+1 -1
View File
@@ -24,7 +24,7 @@
</mat-sidenav>
<div>
<mat-toolbar color="primary">
<button mat-icon-button (click)="start.open()">
<button mat-icon-button (click)="start.open('mouse')">
<mat-icon>menu</mat-icon>
</button>
<div class="demo-toolbar">
+5 -5
View File
@@ -9,9 +9,9 @@
[fixedInViewport]="fixed" [fixedTopGap]="fixedTop" [fixedBottomGap]="fixedBottom">
Start Side Sidenav
<br>
<button mat-button (click)="start.close()">Close</button>
<button mat-button (click)="start.close('mouse')">Close</button>
<br>
<button mat-button (click)="end.open()">Open End Side</button>
<button mat-button (click)="end.open('keyboard')">Open End Side</button>
<br>
<button mat-button (click)="modeIndex = (modeIndex + 1) % 3">Toggle Mode</button>
<div>Mode: {{start.mode}}</div>
@@ -24,7 +24,7 @@
[fixedInViewport]="fixed" [fixedTopGap]="fixedTop" [fixedBottomGap]="fixedBottom">
End Side Sidenav
<br>
<button mat-button (click)="end.close()">Close</button>
<button mat-button (click)="end.close('mouse')">Close</button>
<div class="demo-filler-content" *ngFor="let c of fillerContent">Filler Content</div>
</mat-sidenav>
@@ -39,8 +39,8 @@
<div>
<h3>Sidenav</h3>
<button mat-button (click)="start.toggle()">Toggle Start Side Sidenav</button>
<button mat-button (click)="end.toggle()">Toggle End Side Sidenav</button>
<button mat-button (click)="start.toggle(undefined, 'mouse')">Toggle Start Side Sidenav</button>
<button mat-button (click)="end.toggle(undefined, 'mouse')">Toggle End Side Sidenav</button>
<mat-checkbox [(ngModel)]="fixed">Fixed mode</mat-checkbox>
<mat-checkbox [(ngModel)]="coverHeader">Sidenav covers header/footer</mat-checkbox>
</div>
+6 -3
View File
@@ -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 {
+1 -1
View File
@@ -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;
}
+2 -1
View File
@@ -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);
}
+22 -8
View File
@@ -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<AnimationEvent>();
@@ -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<MatDrawerToggleResult> {
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<MatDrawerToggleResult> {
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<MatDrawerToggleResult> {
toggle(isOpen: boolean = !this.opened, openedVia: FocusOrigin = 'program'):
Promise<MatDrawerToggleResult> {
this._opened = isOpen;
if (isOpen) {
this._animationState = this._enableAnimations ? 'open' : 'open-instant';
this._openedVia = openedVia;
} else {
this._animationState = 'void';
this._restoreFocus();
+2 -1
View File
@@ -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;
}