Skip to content

Commit 7581191

Browse files
zelliottmmalerba
authored andcommitted
feat(material-experimental/chip): add focus indicators (#18261)
1 parent 02db4ba commit 7581191

File tree

14 files changed

+125
-74
lines changed

14 files changed

+125
-74
lines changed

src/material-experimental/mdc-chips/chip-grid.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,14 @@ describe('MDC-based MatChipGrid', () => {
241241
expect(chipGridInstance._keyManager.activeColumnIndex).toBe(0);
242242
}));
243243
});
244+
245+
it('should have a focus indicator', () => {
246+
const focusableTextNativeElements = Array.from(chipGridNativeElement
247+
.querySelectorAll('.mat-chip-row-focusable-text-content'));
248+
249+
expect(focusableTextNativeElements
250+
.every(element => element.classList.contains('mat-mdc-focus-indicator'))).toBe(true);
251+
});
244252
});
245253

246254
describe('keyboard behavior', () => {

src/material-experimental/mdc-chips/chip-icons.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ const _MatChipRemoveMixinBase:
105105
selector: '[matChipRemove]',
106106
inputs: ['disabled', 'tabIndex'],
107107
host: {
108-
'class':
109-
'mat-mdc-chip-remove mat-mdc-chip-trailing-icon mdc-chip__icon mdc-chip__icon--trailing',
108+
'class': `mat-mdc-chip-remove mat-mdc-chip-trailing-icon mat-mdc-focus-indicator
109+
mdc-chip__icon mdc-chip__icon--trailing`,
110110
'[tabIndex]': 'tabIndex',
111111
'role': 'button',
112112
'(click)': 'interaction.next($event)',

src/material-experimental/mdc-chips/chip-option.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
<span class="mdc-chip__ripple"></span>
2+
3+
<span matRipple class="mat-mdc-chip-ripple"
4+
[matRippleAnimation]="_rippleAnimation"
5+
[matRippleDisabled]="_isRippleDisabled()"
6+
[matRippleCentered]="_isRippleCentered"
7+
[matRippleTrigger]="_elementRef.nativeElement"></span>
8+
29
<ng-content select="mat-chip-avatar, [matChipAvatar]"></ng-content>
310
<div class="mdc-chip__checkmark" *ngIf="_chipListMultiple">
411
<svg class="mdc-chip__checkmark-svg" viewBox="-2 -3 30 30">

src/material-experimental/mdc-chips/chip-option.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {SPACE} from '@angular/cdk/keycodes';
33
import {createKeyboardEvent, dispatchFakeEvent} from '@angular/cdk/testing/private';
44
import {Component, DebugElement, ViewChild} from '@angular/core';
55
import {async, ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing';
6-
import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core';
76
import {By} from '@angular/platform-browser';
87
import {chipCssClasses} from '@material/chips';
98
import {Subject} from 'rxjs';
@@ -21,17 +20,14 @@ describe('MDC-based Option Chips', () => {
2120
let chipDebugElement: DebugElement;
2221
let chipNativeElement: HTMLElement;
2322
let chipInstance: MatChipOption;
24-
let globalRippleOptions: RippleGlobalOptions;
2523

2624
let dir = 'ltr';
2725

2826
beforeEach(async(() => {
29-
globalRippleOptions = {};
3027
TestBed.configureTestingModule({
3128
imports: [MatChipsModule],
3229
declarations: [SingleChip],
3330
providers: [
34-
{provide: MAT_RIPPLE_GLOBAL_OPTIONS, useFactory: () => globalRippleOptions},
3531
{provide: Directionality, useFactory: () => ({
3632
value: dir,
3733
change: new Subject()
@@ -286,6 +282,10 @@ describe('MDC-based Option Chips', () => {
286282
const avatar = fixture.nativeElement.querySelector('.avatar');
287283
expect(avatar.classList).toContain(chipCssClasses.HIDDEN_LEADING_ICON);
288284
});
285+
286+
it('should have a focus indicator', () => {
287+
expect(chipNativeElement.classList.contains('mat-mdc-focus-indicator')).toBe(true);
288+
});
289289
});
290290
});
291291

src/material-experimental/mdc-chips/chip-option.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export class MatChipSelectionChange {
4444
inputs: ['color', 'disableRipple', 'tabIndex'],
4545
host: {
4646
'role': 'option',
47+
'class': 'mat-mdc-focus-indicator',
4748
'[class.mat-mdc-chip-disabled]': 'disabled',
4849
'[class.mat-mdc-chip-highlighted]': 'highlighted',
4950
'[class.mat-mdc-chip-with-avatar]': 'leadingIcon',

src/material-experimental/mdc-chips/chip-remove.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ describe('MDC-based Chip Remove', () => {
150150
expect(event.defaultPrevented).toBe(false);
151151
});
152152

153+
it('should have a focus indicator', () => {
154+
const buttonElement = chipNativeElement.querySelector('button')!;
155+
156+
expect(buttonElement.classList.contains('mat-mdc-focus-indicator')).toBe(true);
157+
});
153158
});
154159
});
155160

src/material-experimental/mdc-chips/chip-row.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1+
<span class="mdc-chip__ripple"></span>
2+
3+
<span matRipple class="mat-mdc-chip-ripple"
4+
[matRippleAnimation]="_rippleAnimation"
5+
[matRippleDisabled]="_isRippleDisabled()"
6+
[matRippleCentered]="_isRippleCentered"
7+
[matRippleTrigger]="_elementRef.nativeElement"></span>
8+
19
<div role="gridcell">
2-
<div #chipContent tabindex="-1" class="mat-chip-row-focusable-text-content">
3-
<span class="mdc-chip__ripple"></span>
10+
<div #chipContent tabindex="-1"
11+
class="mat-chip-row-focusable-text-content mat-mdc-focus-indicator">
412
<ng-content select="mat-chip-avatar, [matChipAvatar]"></ng-content>
513
<span class="mdc-chip__text"><ng-content></ng-content></span>
614
<ng-content select="mat-chip-trailing-icon,[matChipTrailingIcon]"></ng-content>

src/material-experimental/mdc-chips/chip-row.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
} from '@angular/cdk/testing/private';
88
import {Component, DebugElement, ViewChild} from '@angular/core';
99
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
10-
import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core';
1110
import {By} from '@angular/platform-browser';
1211
import {Subject} from 'rxjs';
1312
import {MatChipEvent, MatChipGrid, MatChipRow, MatChipsModule} from './index';
@@ -18,17 +17,14 @@ describe('MDC-based Row Chips', () => {
1817
let chipDebugElement: DebugElement;
1918
let chipNativeElement: HTMLElement;
2019
let chipInstance: MatChipRow;
21-
let globalRippleOptions: RippleGlobalOptions;
2220

2321
let dir = 'ltr';
2422

2523
beforeEach(async(() => {
26-
globalRippleOptions = {};
2724
TestBed.configureTestingModule({
2825
imports: [MatChipsModule],
2926
declarations: [SingleChip],
3027
providers: [
31-
{provide: MAT_RIPPLE_GLOBAL_OPTIONS, useFactory: () => globalRippleOptions},
3228
{provide: Directionality, useFactory: () => ({
3329
value: dir,
3430
change: new Subject()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
<span class="mdc-chip__ripple"></span>
2+
3+
<span matRipple class="mat-mdc-chip-ripple"
4+
[matRippleAnimation]="_rippleAnimation"
5+
[matRippleDisabled]="_isRippleDisabled()"
6+
[matRippleCentered]="_isRippleCentered"
7+
[matRippleTrigger]="_elementRef.nativeElement"></span>
8+
29
<ng-content select="mat-chip-avatar, [matChipAvatar]"></ng-content>
310
<div class="mdc-chip__text mdc-chip__action--primary"><ng-content></ng-content></div>
411
<ng-content select="mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]"></ng-content>

src/material-experimental/mdc-chips/chip.spec.ts

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Directionality} from '@angular/cdk/bidi';
22
import {createFakeEvent} from '@angular/cdk/testing/private';
33
import {Component, DebugElement, ViewChild} from '@angular/core';
44
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
5-
import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core';
5+
import {MatRipple} from '@angular/material/core';
66
import {By} from '@angular/platform-browser';
77
import {Subject} from 'rxjs';
88
import {MatChip, MatChipEvent, MatChipSet, MatChipsModule} from './index';
@@ -13,12 +13,12 @@ describe('MDC-based MatChip', () => {
1313
let chipDebugElement: DebugElement;
1414
let chipNativeElement: HTMLElement;
1515
let chipInstance: MatChip;
16-
let globalRippleOptions: RippleGlobalOptions;
16+
let chipRippleDebugElement: DebugElement;
17+
let chipRippleInstance: MatRipple;
1718

1819
let dir = 'ltr';
1920

2021
beforeEach(async(() => {
21-
globalRippleOptions = {};
2222
TestBed.configureTestingModule({
2323
imports: [MatChipsModule],
2424
declarations: [
@@ -28,7 +28,6 @@ describe('MDC-based MatChip', () => {
2828
BasicChipWithBoundTabindex,
2929
],
3030
providers: [
31-
{provide: MAT_RIPPLE_GLOBAL_OPTIONS, useFactory: () => globalRippleOptions},
3231
{provide: Directionality, useFactory: () => ({
3332
value: dir,
3433
change: new Subject()
@@ -76,6 +75,15 @@ describe('MDC-based MatChip', () => {
7675

7776
expect(chip.getAttribute('tabindex')).toBe('15');
7877
});
78+
79+
it('should have its ripple disabled', () => {
80+
fixture = TestBed.createComponent(BasicChip);
81+
fixture.detectChanges();
82+
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
83+
chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
84+
chipRippleInstance = chipRippleDebugElement.injector.get<MatRipple>(MatRipple);
85+
expect(chipRippleInstance.disabled).toBe(true, 'Expected basic chip ripples to be disabled.');
86+
});
7987
});
8088

8189
describe('MatChip', () => {
@@ -88,6 +96,8 @@ describe('MDC-based MatChip', () => {
8896
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
8997
chipNativeElement = chipDebugElement.nativeElement;
9098
chipInstance = chipDebugElement.injector.get<MatChip>(MatChip);
99+
chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
100+
chipRippleInstance = chipRippleDebugElement.injector.get<MatRipple>(MatRipple);
91101
testComponent = fixture.debugElement.componentInstance;
92102
});
93103

@@ -143,12 +153,22 @@ describe('MDC-based MatChip', () => {
143153
expect(chipNativeElement.style.display).toBe('none');
144154
});
145155

146-
it('should be able to disable ripples through ripple global options at runtime', () => {
147-
expect(chipInstance.rippleDisabled).toBe(false, 'Expected chip ripples to be enabled.');
156+
it('should be able to disable ripples with the `[rippleDisabled]` input', () => {
157+
expect(chipRippleInstance.disabled).toBe(false, 'Expected chip ripples to be enabled.');
158+
159+
testComponent.rippleDisabled = true;
160+
fixture.detectChanges();
161+
162+
expect(chipRippleInstance.disabled).toBe(true, 'Expected chip ripples to be disabled.');
163+
});
164+
165+
it('should disable ripples when the chip is disabled', () => {
166+
expect(chipRippleInstance.disabled).toBe(false, 'Expected chip ripples to be enabled.');
148167

149-
globalRippleOptions.disabled = true;
168+
testComponent.disabled = true;
169+
fixture.detectChanges();
150170

151-
expect(chipInstance.rippleDisabled).toBe(true, 'Expected chip ripples to be disabled.');
171+
expect(chipRippleInstance.disabled).toBe(true, 'Expected chip ripples to be disabled.');
152172
});
153173

154174
it('should update the aria-label for disabled chips', () => {
@@ -191,7 +211,7 @@ describe('MDC-based MatChip', () => {
191211
<mat-chip [removable]="removable"
192212
[color]="color" [disabled]="disabled"
193213
(focus)="chipFocus($event)" (destroyed)="chipDestroy($event)"
194-
(removed)="chipRemove($event)" [value]="value">
214+
(removed)="chipRemove($event)" [value]="value" [disableRipple]="rippleDisabled">
195215
{{name}}
196216
</mat-chip>
197217
</div>
@@ -205,6 +225,7 @@ class SingleChip {
205225
removable: boolean = true;
206226
shouldShow: boolean = true;
207227
value: any;
228+
rippleDisabled: boolean = false;
208229

209230
chipFocus: (event?: MatChipEvent) => void = () => {};
210231
chipDestroy: (event?: MatChipEvent) => void = () => {};

0 commit comments

Comments
 (0)