From 32aa4614dd270c69cf07e25c06fd4462701ca24a Mon Sep 17 00:00:00 2001 From: Brian Nenninger Date: Mon, 25 Jul 2016 23:50:14 -0400 Subject: [PATCH] feat(button): add ripple to md-button --- src/components/button/README.md | 1 + src/components/button/button.html | 5 +++++ src/components/button/button.scss | 17 +++++++++++++++++ src/components/button/button.spec.ts | 20 +++++++++++++++++++- src/components/button/button.ts | 23 ++++++++++++++++++++++- src/demo-app/ripple/ripple-demo.html | 9 +++++---- src/demo-app/ripple/ripple-demo.ts | 2 ++ 7 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/components/button/README.md b/src/components/button/README.md index 5e6161961e9c..3dc9923f6183 100644 --- a/src/components/button/README.md +++ b/src/components/button/README.md @@ -112,3 +112,4 @@ Properties: | --- | --- | --- | | `color` | `"primary"|"accent"|"warn"` | The color palette of the button | `disabled` | boolean | Whether or not the button is disabled +| `disableRipple` | boolean | Whether the ripple effect when the button is clicked should be disabled diff --git a/src/components/button/button.html b/src/components/button/button.html index 4e3df0e22666..a1636be45494 100644 --- a/src/components/button/button.html +++ b/src/components/button/button.html @@ -1 +1,6 @@ +
diff --git a/src/components/button/button.scss b/src/components/button/button.scss index 2d5e366a549b..ff0eb85ed88b 100644 --- a/src/components/button/button.scss +++ b/src/components/button/button.scss @@ -43,6 +43,23 @@ } } +// The ripple container should match the bounds of the entire button. +.md-button-ripple { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; +} + +// For round buttons, the ripple container should clip child ripples to a circle. +.md-button-ripple-round { + border-radius: 50%; + // z-index needed to make clipping to border-radius work correctly. + // http://stackoverflow.com/questions/20001515/chrome-bug-border-radius-not-clipping-contents-when-combined-with-css-transiti + z-index: 1; +} + // Only flat buttons and icon buttons (not raised or fabs) have a hover style. [md-button]:hover, [md-icon-button]:hover { // Use the same visual treatment for hover as for focus. diff --git a/src/components/button/button.spec.ts b/src/components/button/button.spec.ts index ba495bf9e7b9..9ceffa753e7b 100644 --- a/src/components/button/button.spec.ts +++ b/src/components/button/button.spec.ts @@ -143,6 +143,23 @@ describe('MdButton', () => { }); }); + + // Ripple tests. + describe('button ripples', () => { + it('should remove ripple if md-ripple-disabled input is set', async(() => { + builder.createAsync(TestApp).then(fixture => { + let testComponent = fixture.debugElement.componentInstance; + let buttonDebugElement = fixture.debugElement.query(By.css('button')); + + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.querySelectorAll('[md-ripple]').length).toBe(1); + + testComponent.rippleDisabled = true; + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.querySelectorAll('[md-ripple]').length).toBe(0); + }); + })); + }); }); /** Test component that contains an MdButton. */ @@ -150,7 +167,7 @@ describe('MdButton', () => { selector: 'test-app', template: ` Link @@ -159,6 +176,7 @@ describe('MdButton', () => { class TestApp { clickCount: number = 0; isDisabled: boolean = false; + rippleDisabled: boolean = false; increment() { this.clickCount++; diff --git a/src/components/button/button.ts b/src/components/button/button.ts index 5c519e047c63..c1cbcf463784 100644 --- a/src/components/button/button.ts +++ b/src/components/button/button.ts @@ -9,8 +9,9 @@ import { Type, NgModule, } from '@angular/core'; +import {MD_RIPPLE_DIRECTIVES} from '@angular2-material/core/core'; +import {BooleanFieldValue} from '@angular2-material/core/annotations/field-value'; -// TODO(jelbourn): Ink ripples. // TODO(jelbourn): Make the `isMouseDown` stuff done with one global listener. // TODO(kara): Convert attribute selectors to classes when attr maps become available @@ -28,6 +29,7 @@ import { }, templateUrl: 'button.html', styleUrls: ['button.css'], + directives: [MD_RIPPLE_DIRECTIVES], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) @@ -40,6 +42,9 @@ export class MdButton { /** Whether a mousedown has occurred on this element in the last 100ms. */ _isMouseDown: boolean = false; + /** Whether the ripple effect on click should be disabled. */ + @Input() @BooleanFieldValue() disableRipple: boolean = false; + constructor(private _elementRef: ElementRef, private _renderer: Renderer) { } get color(): string { @@ -83,6 +88,21 @@ export class MdButton { focus() { this._elementRef.nativeElement.focus(); } + + getHostElement() { + return this._elementRef.nativeElement; + } + + isRoundButton() { + const el = this._elementRef.nativeElement; + return el.hasAttribute('md-icon-button') || + el.hasAttribute('md-fab') || + el.hasAttribute('md-mini-fab'); + } + + isRippleEnabled() { + return !this.disableRipple; + } } @Component({ @@ -98,6 +118,7 @@ export class MdButton { }, templateUrl: 'button.html', styleUrls: ['button.css'], + directives: [MD_RIPPLE_DIRECTIVES], encapsulation: ViewEncapsulation.None }) export class MdAnchor extends MdButton { diff --git a/src/demo-app/ripple/ripple-demo.html b/src/demo-app/ripple/ripple-demo.html index 9f09de717d09..f658df015350 100644 --- a/src/demo-app/ripple/ripple-demo.html +++ b/src/demo-app/ripple/ripple-demo.html @@ -1,12 +1,13 @@
- - - + + -
diff --git a/src/demo-app/ripple/ripple-demo.ts b/src/demo-app/ripple/ripple-demo.ts index 4b9f89c11a9a..5072879b58d7 100644 --- a/src/demo-app/ripple/ripple-demo.ts +++ b/src/demo-app/ripple/ripple-demo.ts @@ -20,6 +20,8 @@ export class RippleDemo { rippleColor = ''; rippleBackgroundColor = ''; + disableButtonRipples = false; + doManualRipple() { if (this.manualRipple) { window.setTimeout(() => this.manualRipple.start(), 10);