fix(button): use FocusOriginMonitor for focus styles (#3294)

* use FocusOriginMonitor for md-button focus styles

* format imports

* fix tests

* export style module

* remove style module import in test

* don't re-export StylModule

* clean up imports

* add back stopImmediatePropagation
This commit is contained in:
mmalerba
2017-03-09 13:57:53 -08:00
committed by tinayuangao
parent dcc857664c
commit 5d6920dde6
5 changed files with 38 additions and 57 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ $mat-mini-fab-padding: 8px !default;
cursor: default;
}
&.mat-button-focus {
&.cdk-keyboard-focused {
.mat-button-focus-overlay {
opacity: 1;
}
+1 -1
View File
@@ -54,7 +54,7 @@
$foreground: map-get($theme, foreground);
.mat-button, .mat-icon-button, .mat-raised-button, .mat-fab, .mat-mini-fab {
&.mat-button-focus {
&.cdk-keyboard-focused {
@include _mat-button-focus-color($theme);
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
import {async, TestBed, ComponentFixture} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component} from '@angular/core';
import {By} from '@angular/platform-browser';
import {MdButtonModule} from './index';
+19 -43
View File
@@ -1,17 +1,17 @@
import {
Component,
ViewEncapsulation,
Input,
HostBinding,
ChangeDetectionStrategy,
ElementRef,
Renderer,
Component,
Directive,
ElementRef,
HostBinding,
Input,
OnDestroy,
Renderer,
ViewEncapsulation
} from '@angular/core';
import {coerceBooleanProperty} from '../core';
import {coerceBooleanProperty, FocusOriginMonitor} from '../core';
// TODO(jelbourn): Make the `isMouseDown` stuff done with one global listener.
// TODO(kara): Convert attribute selectors to classes when attr maps become available
@@ -90,25 +90,15 @@ export class MdMiniFabCssMatStyler {}
'button[mat-fab], button[mat-mini-fab]',
host: {
'[disabled]': 'disabled',
'[class.mat-button-focus]': '_isKeyboardFocused',
'(mousedown)': '_setMousedown()',
'(focus)': '_setKeyboardFocus()',
'(blur)': '_removeKeyboardFocus()',
},
templateUrl: 'button.html',
styleUrls: ['button.css'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MdButton {
export class MdButton implements OnDestroy {
private _color: string;
/** Whether the button has focus from the keyboard (not the mouse). Used for class binding. */
_isKeyboardFocused: boolean = false;
/** Whether a mousedown has occurred on this element in the last 100ms. */
_isMouseDown: boolean = false;
/** Whether the button is round. */
_isRoundButton: boolean = ['icon-button', 'fab', 'mini-fab'].some(suffix => {
let el = this._getHostElement();
@@ -129,22 +119,20 @@ export class MdButton {
get disabled() { return this._disabled; }
set disabled(value: boolean) { this._disabled = coerceBooleanProperty(value) ? true : null; }
constructor(private _elementRef: ElementRef, private _renderer: Renderer) { }
constructor(private _elementRef: ElementRef, private _renderer: Renderer,
private _focusOriginMonitor: FocusOriginMonitor) {
this._focusOriginMonitor.monitor(this._elementRef.nativeElement, this._renderer, true);
}
ngOnDestroy() {
this._focusOriginMonitor.unmonitor(this._elementRef.nativeElement);
}
/** The color of the button. Can be `primary`, `accent`, or `warn`. */
@Input()
get color(): string { return this._color; }
set color(value: string) { this._updateColor(value); }
_setMousedown() {
// We only *show* the focus style when focus has come to the button via the keyboard.
// The Material Design spec is silent on this topic, and without doing this, the
// button continues to look :active after clicking.
// @see http://marcysutton.com/button-focus-hell/
this._isMouseDown = true;
setTimeout(() => { this._isMouseDown = false; }, 100);
}
_updateColor(newColor: string) {
this._setElementColor(this._color, false);
this._setElementColor(newColor, true);
@@ -157,14 +145,6 @@ export class MdButton {
}
}
_setKeyboardFocus() {
this._isKeyboardFocused = !this._isMouseDown;
}
_removeKeyboardFocus() {
this._isKeyboardFocused = false;
}
/** Focuses the button. */
focus(): void {
this._renderer.invokeElementMethod(this._getHostElement(), 'focus');
@@ -189,10 +169,6 @@ export class MdButton {
host: {
'[attr.disabled]': 'disabled',
'[attr.aria-disabled]': '_isAriaDisabled',
'[class.mat-button-focus]': '_isKeyboardFocused',
'(mousedown)': '_setMousedown()',
'(focus)': '_setKeyboardFocus()',
'(blur)': '_removeKeyboardFocus()',
'(click)': '_haltDisabledEvents($event)',
},
templateUrl: 'button.html',
@@ -200,8 +176,8 @@ export class MdButton {
encapsulation: ViewEncapsulation.None
})
export class MdAnchor extends MdButton {
constructor(elementRef: ElementRef, renderer: Renderer) {
super(elementRef, renderer);
constructor(elementRef: ElementRef, renderer: Renderer, focusOriginMonitor: FocusOriginMonitor) {
super(elementRef, renderer, focusOriginMonitor);
}
/** @docs-private */
+16 -11
View File
@@ -1,19 +1,27 @@
import {NgModule, ModuleWithProviders} from '@angular/core';
import {ModuleWithProviders, NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {MdRippleModule, CompatibilityModule} from '../core';
import {CompatibilityModule, MdRippleModule, StyleModule} from '../core';
import {
MdButton,
MdAnchor,
MdButton,
MdButtonCssMatStyler,
MdRaisedButtonCssMatStyler,
MdIconButtonCssMatStyler,
MdFabCssMatStyler,
MdIconButtonCssMatStyler,
MdMiniFabCssMatStyler,
MdRaisedButtonCssMatStyler
} from './button';
export * from './button';
@NgModule({
imports: [CommonModule, MdRippleModule, CompatibilityModule],
imports: [
CommonModule,
MdRippleModule,
CompatibilityModule,
StyleModule,
],
exports: [
MdButton,
MdAnchor,
@@ -22,7 +30,7 @@ import {
MdRaisedButtonCssMatStyler,
MdIconButtonCssMatStyler,
MdFabCssMatStyler,
MdMiniFabCssMatStyler
MdMiniFabCssMatStyler,
],
declarations: [
MdButton,
@@ -31,7 +39,7 @@ import {
MdRaisedButtonCssMatStyler,
MdIconButtonCssMatStyler,
MdFabCssMatStyler,
MdMiniFabCssMatStyler
MdMiniFabCssMatStyler,
],
})
export class MdButtonModule {
@@ -43,6 +51,3 @@ export class MdButtonModule {
};
}
}
export * from './button';