-
+
diff --git a/src/material-experimental/mdc-chips/chip-row.spec.ts b/src/material-experimental/mdc-chips/chip-row.spec.ts
index e3255903a303..8c561811a93a 100644
--- a/src/material-experimental/mdc-chips/chip-row.spec.ts
+++ b/src/material-experimental/mdc-chips/chip-row.spec.ts
@@ -7,7 +7,6 @@ import {
} from '@angular/cdk/testing/private';
import {Component, DebugElement, ViewChild} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
-import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core';
import {By} from '@angular/platform-browser';
import {Subject} from 'rxjs';
import {MatChipEvent, MatChipGrid, MatChipRow, MatChipsModule} from './index';
@@ -18,17 +17,14 @@ describe('MDC-based Row Chips', () => {
let chipDebugElement: DebugElement;
let chipNativeElement: HTMLElement;
let chipInstance: MatChipRow;
- let globalRippleOptions: RippleGlobalOptions;
let dir = 'ltr';
beforeEach(async(() => {
- globalRippleOptions = {};
TestBed.configureTestingModule({
imports: [MatChipsModule],
declarations: [SingleChip],
providers: [
- {provide: MAT_RIPPLE_GLOBAL_OPTIONS, useFactory: () => globalRippleOptions},
{provide: Directionality, useFactory: () => ({
value: dir,
change: new Subject()
diff --git a/src/material-experimental/mdc-chips/chip.html b/src/material-experimental/mdc-chips/chip.html
index 35e5f40a5c2e..73c38b4b4f6d 100644
--- a/src/material-experimental/mdc-chips/chip.html
+++ b/src/material-experimental/mdc-chips/chip.html
@@ -1,4 +1,11 @@
+
+
+
diff --git a/src/material-experimental/mdc-chips/chip.spec.ts b/src/material-experimental/mdc-chips/chip.spec.ts
index d4c9b7125913..870293f99f9b 100644
--- a/src/material-experimental/mdc-chips/chip.spec.ts
+++ b/src/material-experimental/mdc-chips/chip.spec.ts
@@ -2,7 +2,7 @@ import {Directionality} from '@angular/cdk/bidi';
import {createFakeEvent} from '@angular/cdk/testing/private';
import {Component, DebugElement, ViewChild} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
-import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core';
+import {MatRipple} from '@angular/material/core';
import {By} from '@angular/platform-browser';
import {Subject} from 'rxjs';
import {MatChip, MatChipEvent, MatChipSet, MatChipsModule} from './index';
@@ -13,17 +13,16 @@ describe('MDC-based MatChip', () => {
let chipDebugElement: DebugElement;
let chipNativeElement: HTMLElement;
let chipInstance: MatChip;
- let globalRippleOptions: RippleGlobalOptions;
+ let chipRippleDebugElement: DebugElement;
+ let chipRippleInstance: MatRipple;
let dir = 'ltr';
beforeEach(async(() => {
- globalRippleOptions = {};
TestBed.configureTestingModule({
imports: [MatChipsModule],
declarations: [BasicChip, SingleChip],
providers: [
- {provide: MAT_RIPPLE_GLOBAL_OPTIONS, useFactory: () => globalRippleOptions},
{provide: Directionality, useFactory: () => ({
value: dir,
change: new Subject()
@@ -35,7 +34,6 @@ describe('MDC-based MatChip', () => {
}));
describe('MatBasicChip', () => {
-
beforeEach(() => {
fixture = TestBed.createComponent(BasicChip);
fixture.detectChanges();
@@ -43,11 +41,17 @@ describe('MDC-based MatChip', () => {
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
chipNativeElement = chipDebugElement.nativeElement;
chipInstance = chipDebugElement.injector.get
(MatChip);
+ chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
+ chipRippleInstance = chipRippleDebugElement.injector.get(MatRipple);
});
it('adds the `mat-mdc-basic-chip` class', () => {
expect(chipNativeElement.classList).toContain('mat-mdc-basic-chip');
});
+
+ it('should have its ripple disabled', () => {
+ expect(chipRippleInstance.disabled).toBe(true, 'Expected basic chip ripples to be disabled.');
+ });
});
describe('MatChip', () => {
@@ -60,6 +64,8 @@ describe('MDC-based MatChip', () => {
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
chipNativeElement = chipDebugElement.nativeElement;
chipInstance = chipDebugElement.injector.get(MatChip);
+ chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
+ chipRippleInstance = chipRippleDebugElement.injector.get(MatRipple);
testComponent = fixture.debugElement.componentInstance;
});
@@ -115,12 +121,22 @@ describe('MDC-based MatChip', () => {
expect(chipNativeElement.style.display).toBe('none');
});
- it('should be able to disable ripples through ripple global options at runtime', () => {
- expect(chipInstance.rippleDisabled).toBe(false, 'Expected chip ripples to be enabled.');
+ it('should be able to disable ripples with the `[rippleDisabled]` input', () => {
+ expect(chipRippleInstance.disabled).toBe(false, 'Expected chip ripples to be enabled.');
+
+ testComponent.rippleDisabled = true;
+ fixture.detectChanges();
+
+ expect(chipRippleInstance.disabled).toBe(true, 'Expected chip ripples to be disabled.');
+ });
+
+ it('should disable ripples when the chip is disabled', () => {
+ expect(chipRippleInstance.disabled).toBe(false, 'Expected chip ripples to be enabled.');
- globalRippleOptions.disabled = true;
+ testComponent.disabled = true;
+ fixture.detectChanges();
- expect(chipInstance.rippleDisabled).toBe(true, 'Expected chip ripples to be disabled.');
+ expect(chipRippleInstance.disabled).toBe(true, 'Expected chip ripples to be disabled.');
});
it('should update the aria-label for disabled chips', () => {
@@ -163,7 +179,7 @@ describe('MDC-based MatChip', () => {
+ (removed)="chipRemove($event)" [value]="value" [disableRipple]="rippleDisabled">
{{name}}
@@ -177,6 +193,7 @@ class SingleChip {
removable: boolean = true;
shouldShow: boolean = true;
value: any;
+ rippleDisabled: boolean = false;
chipFocus: (event?: MatChipEvent) => void = () => {};
chipDestroy: (event?: MatChipEvent) => void = () => {};
diff --git a/src/material-experimental/mdc-chips/chip.ts b/src/material-experimental/mdc-chips/chip.ts
index 7983d5c9c5f2..f9367f8ee2b7 100644
--- a/src/material-experimental/mdc-chips/chip.ts
+++ b/src/material-experimental/mdc-chips/chip.ts
@@ -8,7 +8,6 @@
import {Directionality} from '@angular/cdk/bidi';
import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
-import {Platform} from '@angular/cdk/platform';
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
import {
AfterContentInit,
@@ -20,29 +19,28 @@ import {
Directive,
ElementRef,
EventEmitter,
+ HostListener,
Inject,
Input,
NgZone,
OnDestroy,
Optional,
Output,
- ViewEncapsulation, HostListener
+ ViewEncapsulation,
+ ViewChild,
} from '@angular/core';
import {
CanColor,
CanColorCtor,
CanDisableRipple,
CanDisableRippleCtor,
- MAT_RIPPLE_GLOBAL_OPTIONS,
HasTabIndex,
HasTabIndexCtor,
+ MatRipple,
mixinColor,
mixinDisableRipple,
mixinTabIndex,
- RippleConfig,
- RippleGlobalOptions,
- RippleRenderer,
- RippleTarget,
+ RippleAnimationConfig,
} from '@angular/material/core';
import {MDCChipAdapter, MDCChipFoundation} from '@material/chips';
import {numbers} from '@material/ripple';
@@ -114,7 +112,16 @@ const _MatChipMixinBase:
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatChip extends _MatChipMixinBase implements AfterContentInit, AfterViewInit,
- CanColor, CanDisableRipple, HasTabIndex, RippleTarget, OnDestroy {
+ CanColor, CanDisableRipple, HasTabIndex, OnDestroy {
+ /** The ripple animation configuration to use for the chip. */
+ readonly _rippleAnimation: RippleAnimationConfig = {
+ enterDuration: numbers.DEACTIVATION_TIMEOUT_MS,
+ exitDuration: numbers.FG_DEACTIVATION_MS
+ };
+
+ /** Whether the ripple is centered on the chip. */
+ readonly _isRippleCentered = false;
+
/** Emits when the chip is focused. */
readonly _onFocus = new Subject
();
@@ -212,25 +219,6 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
/** Subject that emits when the component has been destroyed. */
protected _destroyed = new Subject();
- /** The ripple renderer for this chip. */
- private _rippleRenderer: RippleRenderer;
-
- /**
- * Ripple configuration for ripples that are launched on pointer down.
- * Implemented as part of RippleTarget.
- * @docs-private
- */
- rippleConfig: RippleConfig & RippleGlobalOptions;
-
- /**
- * Implemented as part of RippleTarget. Whether ripples are disabled on interaction.
- * @docs-private
- */
- get rippleDisabled(): boolean {
- return this.disabled || this.disableRipple || !!this.rippleConfig.disabled ||
- this._isBasicChip();
- }
-
/** The chip's leading icon. */
@ContentChild(MatChipAvatar) leadingIcon: MatChipAvatar;
@@ -240,6 +228,9 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
/** The chip's trailing remove icon. */
@ContentChild(MatChipRemove) removeIcon: MatChipRemove;
+ /** Reference to the MatRipple instance of the chip. */
+ @ViewChild(MatRipple) ripple: MatRipple;
+
/**
* Implementation of the MDC chip adapter interface.
* These methods are called by the chip foundation.
@@ -314,10 +305,7 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
constructor(
public _changeDetectorRef: ChangeDetectorRef,
readonly _elementRef: ElementRef,
- private _platform: Platform,
protected _ngZone: NgZone,
- @Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS)
- private _globalRippleOptions: RippleGlobalOptions | null,
@Optional() private _dir: Directionality,
// @breaking-change 8.0.0 `animationMode` parameter to become required.
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string) {
@@ -331,7 +319,6 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
}
ngAfterViewInit() {
- this._initRipple();
this._chipFoundation.init();
}
@@ -339,7 +326,6 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
this.destroyed.emit({chip: this});
this._destroyed.next();
this._destroyed.complete();
- this._rippleRenderer._removeTriggerEvents();
this._chipFoundation.destroy();
}
@@ -406,21 +392,6 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
this._changeDetectorRef.markForCheck();
}
- /** Initializes the ripple renderer. */
- private _initRipple() {
- this.rippleConfig = this._globalRippleOptions || {};
-
- // Configure ripple animation to match MDC Ripple.
- this.rippleConfig.animation = {
- enterDuration: numbers.DEACTIVATION_TIMEOUT_MS,
- exitDuration: numbers.FG_DEACTIVATION_MS,
- };
-
- this._rippleRenderer =
- new RippleRenderer(this, this._ngZone, this._elementRef, this._platform);
- this._rippleRenderer.setupTriggerEvents(this._elementRef);
- }
-
/** Forwards interaction events to the MDC chip foundation. */
_handleInteraction(event: MouseEvent | KeyboardEvent) {
if (!this.disabled) {
@@ -428,6 +399,11 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
}
}
+ /** Whether or not the ripple should be disabled. */
+ _isRippleDisabled(): boolean {
+ return this.disabled || this.disableRipple || this._isBasicChip();
+ }
+
static ngAcceptInputType_disabled: BooleanInput;
static ngAcceptInputType_removable: BooleanInput;
static ngAcceptInputType_highlighted: BooleanInput;
diff --git a/src/material-experimental/mdc-chips/chips.scss b/src/material-experimental/mdc-chips/chips.scss
index 16ca7f771602..36e9f1721632 100644
--- a/src/material-experimental/mdc-chips/chips.scss
+++ b/src/material-experimental/mdc-chips/chips.scss
@@ -11,10 +11,6 @@
.mat-mdc-chip {
// MDC uses a pointer cursor
cursor: default;
- // Needed to prevent mat-ripple from escaping the chip
- overflow: hidden;
- // Required for the ripple to clip properly in Safari.
- transform: translateZ(0);
@include cdk-high-contrast {
outline: solid 1px;
@@ -26,6 +22,20 @@
}
}
+// The ripple container should match the bounds of the entire chip.
+.mat-mdc-chip-ripple {
+ @include mat-fill;
+
+ // Disable pointer events for the ripple container and state overlay because the container
+ // will overlay the user content and we don't want to disable mouse events on the user content.
+ // Pointer events can be safely disabled because the ripple trigger element is the host element.
+ pointer-events: none;
+
+ // Inherit the border radius from the parent so that state overlay and ripples don't exceed the
+ // parent button boundaries.
+ border-radius: inherit;
+}
+
// The MDC chip styles related to hover and focus states are intertwined with the MDC ripple styles.
// We currently don't use the MDC ripple due to size concerns, therefore we need to add some
// additional styles to restore these states.
@@ -37,6 +47,7 @@
content: '';
pointer-events: none;
opacity: 0;
+ border-radius: inherit;
}
}
@@ -80,3 +91,8 @@ input.mat-mdc-chip-input {
stroke: #000 !important;
}
}
+
+// Needed for the focus indicator.
+.mat-chip-row-focusable-text-content {
+ position: relative;
+}
diff --git a/src/material-experimental/mdc-chips/module.ts b/src/material-experimental/mdc-chips/module.ts
index c1b8b20e5b92..a24ab32ec51a 100644
--- a/src/material-experimental/mdc-chips/module.ts
+++ b/src/material-experimental/mdc-chips/module.ts
@@ -9,7 +9,7 @@
import {ENTER} from '@angular/cdk/keycodes';
import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';
-import {ErrorStateMatcher, MatCommonModule} from '@angular/material/core';
+import {ErrorStateMatcher, MatCommonModule, MatRippleModule} from '@angular/material/core';
import {MatChip, MatChipCssInternalOnly} from './chip';
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
import {MatChipGrid} from './chip-grid';
@@ -36,7 +36,7 @@ const CHIP_DECLARATIONS = [
];
@NgModule({
- imports: [MatCommonModule, CommonModule],
+ imports: [MatCommonModule, CommonModule, MatRippleModule],
exports: CHIP_DECLARATIONS,
declarations: CHIP_DECLARATIONS,
providers: [
diff --git a/src/material-experimental/mdc-helpers/_mdc-helpers.scss b/src/material-experimental/mdc-helpers/_mdc-helpers.scss
index 299ee3ae495c..cb5e65f109fc 100644
--- a/src/material-experimental/mdc-helpers/_mdc-helpers.scss
+++ b/src/material-experimental/mdc-helpers/_mdc-helpers.scss
@@ -236,11 +236,17 @@ $mat-typography-level-mappings: (
// contrastive and renders appropriately.
.mat-mdc-focus-indicator.mdc-button::before,
+ .mat-mdc-focus-indicator.mdc-chip::before,
.mat-mdc-focus-indicator.mdc-fab::before,
.mat-mdc-focus-indicator.mdc-icon-button::before {
margin: $mat-focus-indicator-border-width * -2;
}
+ .mat-mdc-focus-indicator.mat-mdc-chip-remove::before,
+ .mat-mdc-focus-indicator.mat-chip-row-focusable-text-content::before {
+ margin: $mat-focus-indicator-border-width * -1;
+ }
+
.mat-mdc-focus-indicator.mat-mdc-tab::before,
.mat-mdc-focus-indicator.mat-mdc-tab-link::before {
margin: $mat-focus-indicator-border-width * 2;