From 678e65e120d3ebf7bfda5477d3afed0e17113ecf Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Fri, 24 Feb 2017 13:33:47 -0800 Subject: [PATCH 1/8] use FocusOriginMonitor for md-button focus styles --- src/lib/button/_button-base.scss | 2 +- src/lib/button/_button-theme.scss | 2 +- src/lib/button/button.ts | 51 ++++++++----------------------- 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/src/lib/button/_button-base.scss b/src/lib/button/_button-base.scss index 810919549c69..2a354f37ab3d 100644 --- a/src/lib/button/_button-base.scss +++ b/src/lib/button/_button-base.scss @@ -55,7 +55,7 @@ $mat-mini-fab-padding: 8px !default; cursor: default; } - &.mat-button-focus { + &.cdk-keyboard-focused { .mat-button-focus-overlay { opacity: 1; } diff --git a/src/lib/button/_button-theme.scss b/src/lib/button/_button-theme.scss index fdf516d3505f..c77f5dbf202d 100644 --- a/src/lib/button/_button-theme.scss +++ b/src/lib/button/_button-theme.scss @@ -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); } } diff --git a/src/lib/button/button.ts b/src/lib/button/button.ts index 8cddd0d647a3..7e5d9228071f 100644 --- a/src/lib/button/button.ts +++ b/src/lib/button/button.ts @@ -6,12 +6,12 @@ import { ChangeDetectionStrategy, ElementRef, Renderer, - Directive, + Directive, OnDestroy, } from '@angular/core'; import {coerceBooleanProperty} from '../core'; +import {FocusOriginMonitor} from '../core/style/focus-origin-monitor'; -// TODO(jelbourn): Make the `isMouseDown` stuff done with one global listener. // TODO(kara): Convert attribute selectors to classes when attr maps become available @@ -85,25 +85,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(); @@ -124,22 +114,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); @@ -152,14 +140,6 @@ export class MdButton { } } - _setKeyboardFocus() { - this._isKeyboardFocused = !this._isMouseDown; - } - - _removeKeyboardFocus() { - this._isKeyboardFocused = false; - } - /** Focuses the button. */ focus(): void { this._renderer.invokeElementMethod(this._getHostElement(), 'focus'); @@ -184,10 +164,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', @@ -195,8 +171,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 */ @@ -213,7 +189,6 @@ export class MdAnchor extends MdButton { // A disabled button shouldn't apply any actions if (this.disabled) { event.preventDefault(); - event.stopImmediatePropagation(); } } } From cf981d77248fd58419f46990504b01241f940457 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Fri, 24 Feb 2017 13:35:30 -0800 Subject: [PATCH 2/8] format imports --- src/lib/button/button.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/button/button.ts b/src/lib/button/button.ts index 7e5d9228071f..5ef31039d87c 100644 --- a/src/lib/button/button.ts +++ b/src/lib/button/button.ts @@ -1,12 +1,13 @@ import { - Component, - ViewEncapsulation, - Input, - HostBinding, ChangeDetectionStrategy, + Component, + Directive, ElementRef, + HostBinding, + Input, + OnDestroy, Renderer, - Directive, OnDestroy, + ViewEncapsulation } from '@angular/core'; import {coerceBooleanProperty} from '../core'; import {FocusOriginMonitor} from '../core/style/focus-origin-monitor'; From 9aec1c5e596176db597ceef20baecf23d5e5d1db Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Fri, 24 Feb 2017 13:45:20 -0800 Subject: [PATCH 3/8] fix tests --- src/lib/button/button.spec.ts | 3 ++- src/lib/button/index.ts | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/lib/button/button.spec.ts b/src/lib/button/button.spec.ts index aba70a71e02e..2019752afc44 100644 --- a/src/lib/button/button.spec.ts +++ b/src/lib/button/button.spec.ts @@ -4,13 +4,14 @@ import {By} from '@angular/platform-browser'; import {MdButtonModule} from './index'; import {ViewportRuler} from '../core/overlay/position/viewport-ruler'; import {FakeViewportRuler} from '../core/overlay/position/fake-viewport-ruler'; +import {StyleModule} from '../core/style/index'; describe('MdButton', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [MdButtonModule.forRoot()], + imports: [MdButtonModule.forRoot(), StyleModule], declarations: [TestApp], providers: [ {provide: ViewportRuler, useClass: FakeViewportRuler}, diff --git a/src/lib/button/index.ts b/src/lib/button/index.ts index 1f96453f5290..962133b0741b 100644 --- a/src/lib/button/index.ts +++ b/src/lib/button/index.ts @@ -1,22 +1,26 @@ -import {NgModule, ModuleWithProviders} from '@angular/core'; +import {ModuleWithProviders, NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; -import {MdRippleModule, CompatibilityModule} from '../core'; +import {MdRippleModule} from '../core/ripple/ripple'; +import {CompatibilityModule} from '../core/compatibility/compatibility'; import { - MdButton, MdAnchor, + MdButton, MdButtonCssMatStyler, - MdRaisedButtonCssMatStyler, - MdIconButtonCssMatStyler, MdFabCssMatStyler, + MdIconButtonCssMatStyler, MdMiniFabCssMatStyler, + MdRaisedButtonCssMatStyler } from './button'; +import {StyleModule} from '../core/style/index'; + + +export * from './button'; @NgModule({ - imports: [CommonModule, MdRippleModule, CompatibilityModule], + imports: [CommonModule, MdRippleModule, CompatibilityModule, StyleModule], exports: [ - MdButton, - MdAnchor, + MdButton, MdAnchor, CompatibilityModule, MdButtonCssMatStyler, MdRaisedButtonCssMatStyler, @@ -43,6 +47,3 @@ export class MdButtonModule { }; } } - - -export * from './button'; From da6d4f26d99f9ad348e2cddd165f0e4468b2e85b Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Mon, 27 Feb 2017 17:08:09 -0800 Subject: [PATCH 4/8] export style module --- src/lib/button/index.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/lib/button/index.ts b/src/lib/button/index.ts index 962133b0741b..aea544984e9b 100644 --- a/src/lib/button/index.ts +++ b/src/lib/button/index.ts @@ -18,15 +18,22 @@ export * from './button'; @NgModule({ - imports: [CommonModule, MdRippleModule, CompatibilityModule, StyleModule], + imports: [ + CommonModule, + MdRippleModule, + CompatibilityModule, + StyleModule, + ], exports: [ - MdButton, MdAnchor, + MdButton, + MdAnchor, CompatibilityModule, MdButtonCssMatStyler, MdRaisedButtonCssMatStyler, MdIconButtonCssMatStyler, MdFabCssMatStyler, - MdMiniFabCssMatStyler + MdMiniFabCssMatStyler, + StyleModule, ], declarations: [ MdButton, @@ -35,7 +42,7 @@ export * from './button'; MdRaisedButtonCssMatStyler, MdIconButtonCssMatStyler, MdFabCssMatStyler, - MdMiniFabCssMatStyler + MdMiniFabCssMatStyler, ], }) export class MdButtonModule { From 43f9a4d44ed42a7f3676541497a273fa908c4ebc Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Tue, 28 Feb 2017 09:47:52 -0800 Subject: [PATCH 5/8] remove style module import in test --- src/lib/button/button.spec.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/button/button.spec.ts b/src/lib/button/button.spec.ts index 2019752afc44..d010953f47db 100644 --- a/src/lib/button/button.spec.ts +++ b/src/lib/button/button.spec.ts @@ -1,17 +1,16 @@ -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'; import {ViewportRuler} from '../core/overlay/position/viewport-ruler'; import {FakeViewportRuler} from '../core/overlay/position/fake-viewport-ruler'; -import {StyleModule} from '../core/style/index'; describe('MdButton', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [MdButtonModule.forRoot(), StyleModule], + imports: [MdButtonModule.forRoot()], declarations: [TestApp], providers: [ {provide: ViewportRuler, useClass: FakeViewportRuler}, From 350597514e75cc91b08bf4354af29a47455ec3ce Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Tue, 28 Feb 2017 16:46:12 -0800 Subject: [PATCH 6/8] don't re-export StylModule --- src/lib/button/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/button/index.ts b/src/lib/button/index.ts index aea544984e9b..95f3baef3473 100644 --- a/src/lib/button/index.ts +++ b/src/lib/button/index.ts @@ -33,7 +33,6 @@ export * from './button'; MdIconButtonCssMatStyler, MdFabCssMatStyler, MdMiniFabCssMatStyler, - StyleModule, ], declarations: [ MdButton, From 47ff09c54694ec2d54f24207bd9743b540bb41c1 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Mon, 6 Mar 2017 09:52:05 -0800 Subject: [PATCH 7/8] clean up imports --- src/lib/button/button.ts | 3 +-- src/lib/button/index.ts | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lib/button/button.ts b/src/lib/button/button.ts index 5ef31039d87c..c80a786ceab3 100644 --- a/src/lib/button/button.ts +++ b/src/lib/button/button.ts @@ -9,8 +9,7 @@ import { Renderer, ViewEncapsulation } from '@angular/core'; -import {coerceBooleanProperty} from '../core'; -import {FocusOriginMonitor} from '../core/style/focus-origin-monitor'; +import {coerceBooleanProperty, FocusOriginMonitor} from '../core'; // TODO(kara): Convert attribute selectors to classes when attr maps become available diff --git a/src/lib/button/index.ts b/src/lib/button/index.ts index 95f3baef3473..4d7ddd16408b 100644 --- a/src/lib/button/index.ts +++ b/src/lib/button/index.ts @@ -1,7 +1,6 @@ import {ModuleWithProviders, NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; -import {MdRippleModule} from '../core/ripple/ripple'; -import {CompatibilityModule} from '../core/compatibility/compatibility'; +import {CompatibilityModule, MdRippleModule, StyleModule} from '../core'; import { MdAnchor, MdButton, @@ -11,7 +10,6 @@ import { MdMiniFabCssMatStyler, MdRaisedButtonCssMatStyler } from './button'; -import {StyleModule} from '../core/style/index'; export * from './button'; From 9e5aa1ae29e39bb85565cd259874d9ba39b6dbe4 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Mon, 6 Mar 2017 10:01:59 -0800 Subject: [PATCH 8/8] add back stopImmediatePropagation --- src/lib/button/button.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/button/button.ts b/src/lib/button/button.ts index c80a786ceab3..41d7a7c43a0a 100644 --- a/src/lib/button/button.ts +++ b/src/lib/button/button.ts @@ -189,6 +189,7 @@ export class MdAnchor extends MdButton { // A disabled button shouldn't apply any actions if (this.disabled) { event.preventDefault(); + event.stopImmediatePropagation(); } } }