From 89f82d81109525aad8ac26d17937f133ddce841f Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Wed, 15 Feb 2017 16:53:55 -0800 Subject: [PATCH 1/6] Add a focus overlay for button-toggle --- src/lib/button-toggle/button-toggle.html | 4 +++ src/lib/button-toggle/button-toggle.scss | 30 ++++++++++++++++++++++ src/lib/button-toggle/button-toggle.ts | 32 ++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/lib/button-toggle/button-toggle.html b/src/lib/button-toggle/button-toggle.html index face84340cfa..2f73348c495d 100644 --- a/src/lib/button-toggle/button-toggle.html +++ b/src/lib/button-toggle/button-toggle.html @@ -5,6 +5,8 @@ [checked]="checked" [disabled]="disabled" [name]="name" + (blur)="_onInputBlur()" + (focus)="_onInputFocus()" (change)="_onInputChange($event)" (click)="_onInputClick($event)"> @@ -12,3 +14,5 @@ + +
diff --git a/src/lib/button-toggle/button-toggle.scss b/src/lib/button-toggle/button-toggle.scss index 78a54939c765..7185f4a58ca1 100644 --- a/src/lib/button-toggle/button-toggle.scss +++ b/src/lib/button-toggle/button-toggle.scss @@ -1,4 +1,5 @@ @import '../core/style/elevation'; +@import '../core/a11y/a11y'; $mat-button-toggle-padding: 0 16px !default; $mat-button-toggle-line-height: 36px !default; @@ -34,6 +35,11 @@ $mat-button-toggle-border-radius: 2px !default; .mat-button-toggle { white-space: nowrap; font-family: $mat-font-family; + position: relative; +} + +.mat-button-toggle.mat-button-toggle-focus .mat-button-toggle-focus-overlay { + opacity: 1; } .mat-button-toggle-label-content { @@ -47,3 +53,27 @@ $mat-button-toggle-border-radius: 2px !default; .mat-button-toggle-label-content > * { vertical-align: middle; } + +// Overlay to be used as a tint. Note that the same effect can be achieved by using a pseudo +// element, however we use a proper DOM element in order to be able to disable the default +// touch action. This makes the buttons more responsive on touch devices. +.mat-button-toggle-focus-overlay { + // The button spec calls for focus on raised buttons (and FABs) to be indicated with a + // black, 12% opacity shade over the normal color (for both light and dark themes). + background-color: rgba(black, 0.12); + border-radius: inherit; + pointer-events: none; + opacity: 0; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + + @include cdk-high-contrast { + // Note that IE will render this in the same way, no + // matter whether the theme is light or dark. This helps + // with the readability of focused buttons. + background-color: rgba(white, 0.5); + } +} diff --git a/src/lib/button-toggle/button-toggle.ts b/src/lib/button-toggle/button-toggle.ts index a34cbb15134b..56e99f45d7f1 100644 --- a/src/lib/button-toggle/button-toggle.ts +++ b/src/lib/button-toggle/button-toggle.ts @@ -276,7 +276,6 @@ export class MdButtonToggleGroupMultiple { set vertical(value) { this._vertical = coerceBooleanProperty(value); } - } /** Single button inside of a toggle group. */ @@ -287,13 +286,21 @@ export class MdButtonToggleGroupMultiple { styleUrls: ['button-toggle.css'], encapsulation: ViewEncapsulation.None, host: { - '[class.mat-button-toggle]': 'true' + '[class.mat-button-toggle-focus]': '_hasFocus', + '[class.mat-button-toggle]': 'true', + '(mousedown)': '_setMousedown()', } }) export class MdButtonToggle implements OnInit { /** Whether or not this button toggle is checked. */ private _checked: boolean = false; + /** Whether the button has focus. Used for class binding. */ + _hasFocus: boolean = false; + + /** Whether a mousedown has occurred on this element in the last 100ms. */ + _isMouseDown: boolean = false; + /** Type of the button toggle. Either 'radio' or 'checkbox'. */ _type: ToggleType; @@ -461,10 +468,31 @@ export class MdButtonToggle implements OnInit { event.stopPropagation(); } + _onInputFocus() { + // Only show the focus / ripple indicator when the focus was not triggered by a mouse + // interaction on the component. + if (!this._isMouseDown) { + this._hasFocus = true; + } + } + + _onInputBlur() { + this._hasFocus = false; + } + /** Focuses the button. */ focus() { this._renderer.invokeElementMethod(this._inputElement.nativeElement, 'focus'); } + + _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); + } } From 85ad786c55a074c320a3ed49373c87aef389f4b2 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Thu, 16 Feb 2017 11:46:52 -0800 Subject: [PATCH 2/6] Use FocusOriginMonitor --- src/lib/button-toggle/button-toggle.html | 2 -- src/lib/button-toggle/button-toggle.scss | 2 +- src/lib/button-toggle/button-toggle.ts | 34 +++--------------------- 3 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/lib/button-toggle/button-toggle.html b/src/lib/button-toggle/button-toggle.html index 2f73348c495d..fffdfa7c3e25 100644 --- a/src/lib/button-toggle/button-toggle.html +++ b/src/lib/button-toggle/button-toggle.html @@ -5,8 +5,6 @@ [checked]="checked" [disabled]="disabled" [name]="name" - (blur)="_onInputBlur()" - (focus)="_onInputFocus()" (change)="_onInputChange($event)" (click)="_onInputClick($event)"> diff --git a/src/lib/button-toggle/button-toggle.scss b/src/lib/button-toggle/button-toggle.scss index 7185f4a58ca1..cc9a77b823a1 100644 --- a/src/lib/button-toggle/button-toggle.scss +++ b/src/lib/button-toggle/button-toggle.scss @@ -38,7 +38,7 @@ $mat-button-toggle-border-radius: 2px !default; position: relative; } -.mat-button-toggle.mat-button-toggle-focus .mat-button-toggle-focus-overlay { +.mat-button-toggle.cdk-focused .mat-button-toggle-focus-overlay { opacity: 1; } diff --git a/src/lib/button-toggle/button-toggle.ts b/src/lib/button-toggle/button-toggle.ts index 56e99f45d7f1..a56f6f6d871e 100644 --- a/src/lib/button-toggle/button-toggle.ts +++ b/src/lib/button-toggle/button-toggle.ts @@ -21,6 +21,7 @@ import { import {NG_VALUE_ACCESSOR, ControlValueAccessor, FormsModule} from '@angular/forms'; import {Observable} from 'rxjs/Observable'; import { + FocusOriginMonitor, UniqueSelectionDispatcher, coerceBooleanProperty, UNIQUE_SELECTION_DISPATCHER_PROVIDER, @@ -286,21 +287,13 @@ export class MdButtonToggleGroupMultiple { styleUrls: ['button-toggle.css'], encapsulation: ViewEncapsulation.None, host: { - '[class.mat-button-toggle-focus]': '_hasFocus', '[class.mat-button-toggle]': 'true', - '(mousedown)': '_setMousedown()', } }) export class MdButtonToggle implements OnInit { /** Whether or not this button toggle is checked. */ private _checked: boolean = false; - /** Whether the button has focus. Used for class binding. */ - _hasFocus: boolean = false; - - /** Whether a mousedown has occurred on this element in the last 100ms. */ - _isMouseDown: boolean = false; - /** Type of the button toggle. Either 'radio' or 'checkbox'. */ _type: ToggleType; @@ -339,7 +332,8 @@ export class MdButtonToggle implements OnInit { constructor(@Optional() toggleGroup: MdButtonToggleGroup, @Optional() toggleGroupMultiple: MdButtonToggleGroupMultiple, public buttonToggleDispatcher: UniqueSelectionDispatcher, - private _renderer: Renderer) { + private _renderer: Renderer, + private _focusOriginMonitor: FocusOriginMonitor) { this.buttonToggleGroup = toggleGroup; this.buttonToggleGroupMultiple = toggleGroupMultiple; @@ -370,6 +364,7 @@ export class MdButtonToggle implements OnInit { if (this.buttonToggleGroup && this._value == this.buttonToggleGroup.value) { this._checked = true; } + this._focusOriginMonitor.registerElementForFocusClasses(this._inputElement.nativeElement, this._renderer); } /** Unique ID for the underlying `input` element. */ @@ -468,31 +463,10 @@ export class MdButtonToggle implements OnInit { event.stopPropagation(); } - _onInputFocus() { - // Only show the focus / ripple indicator when the focus was not triggered by a mouse - // interaction on the component. - if (!this._isMouseDown) { - this._hasFocus = true; - } - } - - _onInputBlur() { - this._hasFocus = false; - } - /** Focuses the button. */ focus() { this._renderer.invokeElementMethod(this._inputElement.nativeElement, 'focus'); } - - _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); - } } From 6920d562269fb13efe5256eefa952a1a020d919a Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Thu, 16 Feb 2017 16:29:45 -0800 Subject: [PATCH 3/6] . --- .../button-toggle/_button-toggle-theme.scss | 22 +++++++++++++++++++ src/lib/button-toggle/button-toggle.ts | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/lib/button-toggle/_button-toggle-theme.scss b/src/lib/button-toggle/_button-toggle-theme.scss index 4b7f6c9309f3..8d63ab8cbe1e 100644 --- a/src/lib/button-toggle/_button-toggle-theme.scss +++ b/src/lib/button-toggle/_button-toggle-theme.scss @@ -1,6 +1,24 @@ @import '../core/theming/palette'; @import '../core/theming/theming'; +// Applies a focus style to an md-button-toggle element for each of the supported palettes. +@mixin _mat-button-toggle-focus-color($theme) { + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + + &.mat-primary .mat-button-toggle-focus-overlay { + background-color: mat-color($primary, 0.12); + } + + &.mat-accent .mat-button-toggle-focus-overlay { + background-color: mat-color($accent, 0.12); + } + + &.mat-warn .mat-button-toggle-focus-overlay { + background-color: mat-color($warn, 0.12); + } +} @mixin mat-button-toggle-theme($theme) { $foreground: map-get($theme, foreground); @@ -8,6 +26,10 @@ .mat-button-toggle { color: mat-color($foreground, hint-text); + + &.cdk-focused { + @include _mat-button-toggle-focus-color($theme); + } } .mat-button-toggle-checked { diff --git a/src/lib/button-toggle/button-toggle.ts b/src/lib/button-toggle/button-toggle.ts index a56f6f6d871e..705e24a07711 100644 --- a/src/lib/button-toggle/button-toggle.ts +++ b/src/lib/button-toggle/button-toggle.ts @@ -333,6 +333,7 @@ export class MdButtonToggle implements OnInit { @Optional() toggleGroupMultiple: MdButtonToggleGroupMultiple, public buttonToggleDispatcher: UniqueSelectionDispatcher, private _renderer: Renderer, + private _elementRef: ElementRef, private _focusOriginMonitor: FocusOriginMonitor) { this.buttonToggleGroup = toggleGroup; @@ -364,7 +365,7 @@ export class MdButtonToggle implements OnInit { if (this.buttonToggleGroup && this._value == this.buttonToggleGroup.value) { this._checked = true; } - this._focusOriginMonitor.registerElementForFocusClasses(this._inputElement.nativeElement, this._renderer); + this._focusOriginMonitor.monitor(this._elementRef.nativeElement, this._renderer, true); } /** Unique ID for the underlying `input` element. */ From 61f047143770345b2f356a4e54459ce267db6c2d Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Fri, 17 Feb 2017 10:48:25 -0800 Subject: [PATCH 4/6] Fix test --- src/lib/button-toggle/button-toggle.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/button-toggle/button-toggle.spec.ts b/src/lib/button-toggle/button-toggle.spec.ts index d6907b557ccb..a3a095b17b0a 100644 --- a/src/lib/button-toggle/button-toggle.spec.ts +++ b/src/lib/button-toggle/button-toggle.spec.ts @@ -14,6 +14,7 @@ import { MdButtonToggleGroupMultiple, MdButtonToggleChange, MdButtonToggleModule, } from './button-toggle'; +import {FocusOriginMonitor} from '../core'; describe('MdButtonToggle', () => { @@ -21,6 +22,7 @@ describe('MdButtonToggle', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [MdButtonToggleModule.forRoot(), FormsModule, ReactiveFormsModule], + providers: [FocusOriginMonitor], declarations: [ ButtonTogglesInsideButtonToggleGroup, ButtonToggleGroupWithNgModel, From a83662459ac76e033362b1cbd21c1c3d9fd584e7 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Fri, 17 Feb 2017 16:20:36 -0800 Subject: [PATCH 5/6] Add 0.12 opacity white and black. --- .../button-toggle/_button-toggle-theme.scss | 16 +++------------- src/lib/button-toggle/button-toggle.scss | 19 +++---------------- src/lib/button-toggle/button-toggle.spec.ts | 2 -- src/lib/button-toggle/button-toggle.ts | 4 ++-- src/lib/core/theming/_palette.scss | 14 ++++++++------ 5 files changed, 16 insertions(+), 39 deletions(-) diff --git a/src/lib/button-toggle/_button-toggle-theme.scss b/src/lib/button-toggle/_button-toggle-theme.scss index 8d63ab8cbe1e..a97abd06721c 100644 --- a/src/lib/button-toggle/_button-toggle-theme.scss +++ b/src/lib/button-toggle/_button-toggle-theme.scss @@ -3,20 +3,10 @@ // Applies a focus style to an md-button-toggle element for each of the supported palettes. @mixin _mat-button-toggle-focus-color($theme) { - $primary: map-get($theme, primary); - $accent: map-get($theme, accent); - $warn: map-get($theme, warn); - - &.mat-primary .mat-button-toggle-focus-overlay { - background-color: mat-color($primary, 0.12); - } - - &.mat-accent .mat-button-toggle-focus-overlay { - background-color: mat-color($accent, 0.12); - } + $foreground: map-get($theme, foreground); - &.mat-warn .mat-button-toggle-focus-overlay { - background-color: mat-color($warn, 0.12); + .mat-button-toggle-focus-overlay { + background-color: mat-color($foreground, divider); } } diff --git a/src/lib/button-toggle/button-toggle.scss b/src/lib/button-toggle/button-toggle.scss index cc9a77b823a1..98c04cb95c08 100644 --- a/src/lib/button-toggle/button-toggle.scss +++ b/src/lib/button-toggle/button-toggle.scss @@ -1,5 +1,6 @@ -@import '../core/style/elevation'; @import '../core/a11y/a11y'; +@import '../core/style/elevation'; +@import '../core/style/layout-common'; $mat-button-toggle-padding: 0 16px !default; $mat-button-toggle-line-height: 36px !default; @@ -58,22 +59,8 @@ $mat-button-toggle-border-radius: 2px !default; // element, however we use a proper DOM element in order to be able to disable the default // touch action. This makes the buttons more responsive on touch devices. .mat-button-toggle-focus-overlay { - // The button spec calls for focus on raised buttons (and FABs) to be indicated with a - // black, 12% opacity shade over the normal color (for both light and dark themes). - background-color: rgba(black, 0.12); border-radius: inherit; pointer-events: none; opacity: 0; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - - @include cdk-high-contrast { - // Note that IE will render this in the same way, no - // matter whether the theme is light or dark. This helps - // with the readability of focused buttons. - background-color: rgba(white, 0.5); - } + @include mat-fill; } diff --git a/src/lib/button-toggle/button-toggle.spec.ts b/src/lib/button-toggle/button-toggle.spec.ts index a3a095b17b0a..d6907b557ccb 100644 --- a/src/lib/button-toggle/button-toggle.spec.ts +++ b/src/lib/button-toggle/button-toggle.spec.ts @@ -14,7 +14,6 @@ import { MdButtonToggleGroupMultiple, MdButtonToggleChange, MdButtonToggleModule, } from './button-toggle'; -import {FocusOriginMonitor} from '../core'; describe('MdButtonToggle', () => { @@ -22,7 +21,6 @@ describe('MdButtonToggle', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [MdButtonToggleModule.forRoot(), FormsModule, ReactiveFormsModule], - providers: [FocusOriginMonitor], declarations: [ ButtonTogglesInsideButtonToggleGroup, ButtonToggleGroupWithNgModel, diff --git a/src/lib/button-toggle/button-toggle.ts b/src/lib/button-toggle/button-toggle.ts index 705e24a07711..7bc964988040 100644 --- a/src/lib/button-toggle/button-toggle.ts +++ b/src/lib/button-toggle/button-toggle.ts @@ -287,7 +287,7 @@ export class MdButtonToggleGroupMultiple { styleUrls: ['button-toggle.css'], encapsulation: ViewEncapsulation.None, host: { - '[class.mat-button-toggle]': 'true', + '[class.mat-button-toggle]': 'true' } }) export class MdButtonToggle implements OnInit { @@ -480,7 +480,7 @@ export class MdButtonToggle implements OnInit { CompatibilityModule, ], declarations: [MdButtonToggleGroup, MdButtonToggleGroupMultiple, MdButtonToggle], - providers: [UNIQUE_SELECTION_DISPATCHER_PROVIDER] + providers: [UNIQUE_SELECTION_DISPATCHER_PROVIDER, FocusOriginMonitor] }) export class MdButtonToggleModule { /** @deprecated */ diff --git a/src/lib/core/theming/_palette.scss b/src/lib/core/theming/_palette.scss index a211a0836914..5cf6442535a6 100644 --- a/src/lib/core/theming/_palette.scss +++ b/src/lib/core/theming/_palette.scss @@ -8,6 +8,8 @@ $black-87-opacity: rgba(black, 0.87); $white-87-opacity: rgba(white, 0.87); +$black-12-opacity: rgba(black, 0.12); +$white-12-opacity: rgba(white, 0.12); $mat-red: ( 50: #ffebee, @@ -649,7 +651,7 @@ $mat-light-theme-background: ( hover: rgba(black, 0.04), // TODO(kara): check style with Material Design UX card: white, dialog: white, - disabled-button: rgba(black, 0.12), + disabled-button: $black-12-opacity, raised-button: white, ); @@ -661,15 +663,15 @@ $mat-dark-theme-background: ( hover: rgba(white, 0.04), // TODO(kara): check style with Material Design UX card: map_get($mat-grey, 800), dialog: map_get($mat-grey, 800), - disabled-button: rgba(white, 0.12), + disabled-button: $white-12-opacity, raised-button: map-get($mat-grey, 800), ); // Foreground palette for light themes. $mat-light-theme-foreground: ( base: black, - divider: rgba(black, 0.12), - dividers: rgba(black, 0.12), + divider: $black-12-opacity, + dividers: $black-12-opacity, disabled: rgba(black, 0.38), disabled-button: rgba(black, 0.38), disabled-text: rgba(black, 0.38), @@ -683,8 +685,8 @@ $mat-light-theme-foreground: ( // Foreground palette for dark themes. $mat-dark-theme-foreground: ( base: white, - divider: rgba(white, 0.12), - dividers: rgba(white, 0.12), + divider: $white-12-opacity, + dividers: $white-12-opacity, disabled: rgba(white, 0.3), disabled-button: rgba(white, 0.3), disabled-text: rgba(white, 0.3), From 7a23190789725359476154b007143cfc8aa8e7a7 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Fri, 17 Feb 2017 16:52:25 -0800 Subject: [PATCH 6/6] Add dark-overlay --- src/lib/button-toggle/_button-toggle-theme.scss | 4 ++-- src/lib/core/theming/_palette.scss | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/button-toggle/_button-toggle-theme.scss b/src/lib/button-toggle/_button-toggle-theme.scss index a97abd06721c..4da2ad51bf19 100644 --- a/src/lib/button-toggle/_button-toggle-theme.scss +++ b/src/lib/button-toggle/_button-toggle-theme.scss @@ -3,10 +3,10 @@ // Applies a focus style to an md-button-toggle element for each of the supported palettes. @mixin _mat-button-toggle-focus-color($theme) { - $foreground: map-get($theme, foreground); + $background: map-get($theme, background); .mat-button-toggle-focus-overlay { - background-color: mat-color($foreground, divider); + background-color: mat-color($background, dark-overlay); } } diff --git a/src/lib/core/theming/_palette.scss b/src/lib/core/theming/_palette.scss index 5cf6442535a6..00c85649459b 100644 --- a/src/lib/core/theming/_palette.scss +++ b/src/lib/core/theming/_palette.scss @@ -653,6 +653,7 @@ $mat-light-theme-background: ( dialog: white, disabled-button: $black-12-opacity, raised-button: white, + dark-overlay: $black-12-opacity, ); // Background palette for dark themes. @@ -665,6 +666,7 @@ $mat-dark-theme-background: ( dialog: map_get($mat-grey, 800), disabled-button: $white-12-opacity, raised-button: map-get($mat-grey, 800), + dark-overlay: $white-12-opacity, ); // Foreground palette for light themes.