Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(material-experimental/chip): Add focus indicators #18261

Merged
merged 5 commits into from
Jan 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/material-experimental/mdc-chips/chip-grid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,14 @@ describe('MDC-based MatChipGrid', () => {
expect(chipGridInstance._keyManager.activeColumnIndex).toBe(0);
}));
});

it('should have a focus indicator', () => {
const focusableTextNativeElements = Array.from(chipGridNativeElement
.querySelectorAll('.mat-chip-row-focusable-text-content'));

expect(focusableTextNativeElements
.every(element => element.classList.contains('mat-mdc-focus-indicator'))).toBe(true);
});
});

describe('keyboard behavior', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/material-experimental/mdc-chips/chip-icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ const _MatChipRemoveMixinBase:
selector: '[matChipRemove]',
inputs: ['disabled', 'tabIndex'],
host: {
'class':
'mat-mdc-chip-remove mat-mdc-chip-trailing-icon mdc-chip__icon mdc-chip__icon--trailing',
'class': `mat-mdc-chip-remove mat-mdc-chip-trailing-icon mat-mdc-focus-indicator
mdc-chip__icon mdc-chip__icon--trailing`,
'[tabIndex]': 'tabIndex',
'role': 'button',
'(click)': 'interaction.next($event)',
Expand Down
7 changes: 7 additions & 0 deletions src/material-experimental/mdc-chips/chip-option.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
<span class="mdc-chip__ripple"></span>

<span matRipple class="mat-mdc-chip-ripple"
[matRippleAnimation]="_rippleAnimation"
[matRippleDisabled]="_isRippleDisabled()"
[matRippleCentered]="_isRippleCentered"
[matRippleTrigger]="_elementRef.nativeElement"></span>

<ng-content select="mat-chip-avatar, [matChipAvatar]"></ng-content>
<div class="mdc-chip__checkmark" *ngIf="_chipListMultiple">
<svg class="mdc-chip__checkmark-svg" viewBox="-2 -3 30 30">
Expand Down
8 changes: 4 additions & 4 deletions src/material-experimental/mdc-chips/chip-option.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {SPACE} from '@angular/cdk/keycodes';
import {createKeyboardEvent, dispatchFakeEvent} from '@angular/cdk/testing/private';
import {Component, DebugElement, ViewChild} from '@angular/core';
import {async, ComponentFixture, fakeAsync, flush, 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 {
Expand All @@ -20,17 +19,14 @@ describe('MDC-based Option Chips', () => {
let chipDebugElement: DebugElement;
let chipNativeElement: HTMLElement;
let chipInstance: MatChipOption;
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()
Expand Down Expand Up @@ -269,6 +265,10 @@ describe('MDC-based Option Chips', () => {
expect(chipNativeElement.getAttribute('aria-disabled')).toBe('true');
});
});

it('should have a focus indicator', () => {
expect(chipNativeElement.classList.contains('mat-mdc-focus-indicator')).toBe(true);
});
});
});

Expand Down
1 change: 1 addition & 0 deletions src/material-experimental/mdc-chips/chip-option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export class MatChipSelectionChange {
inputs: ['color', 'disableRipple', 'tabIndex'],
host: {
'role': 'option',
'class': 'mat-mdc-focus-indicator',
'[class.mat-mdc-chip-disabled]': 'disabled',
'[class.mat-mdc-chip-highlighted]': 'highlighted',
'[class.mat-mdc-chip-with-avatar]': 'leadingIcon',
Expand Down
5 changes: 5 additions & 0 deletions src/material-experimental/mdc-chips/chip-remove.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ describe('MDC-based Chip Remove', () => {
expect(event.defaultPrevented).toBe(false);
});

it('should have a focus indicator', () => {
const buttonElement = chipNativeElement.querySelector('button')!;

expect(buttonElement.classList.contains('mat-mdc-focus-indicator')).toBe(true);
});
});
});

Expand Down
12 changes: 10 additions & 2 deletions src/material-experimental/mdc-chips/chip-row.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
<span class="mdc-chip__ripple"></span>

<span matRipple class="mat-mdc-chip-ripple"
[matRippleAnimation]="_rippleAnimation"
[matRippleDisabled]="_isRippleDisabled()"
[matRippleCentered]="_isRippleCentered"
[matRippleTrigger]="_elementRef.nativeElement"></span>

<div role="gridcell">
<div #chipContent tabindex="-1" class="mat-chip-row-focusable-text-content">
<span class="mdc-chip__ripple"></span>
<div #chipContent tabindex="-1"
class="mat-chip-row-focusable-text-content mat-mdc-focus-indicator">
<ng-content select="mat-chip-avatar, [matChipAvatar]"></ng-content>
<span class="mdc-chip__text"><ng-content></ng-content></span>
<ng-content select="mat-chip-trailing-icon,[matChipTrailingIcon]"></ng-content>
Expand Down
4 changes: 0 additions & 4 deletions src/material-experimental/mdc-chips/chip-row.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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()
Expand Down
7 changes: 7 additions & 0 deletions src/material-experimental/mdc-chips/chip.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
<span class="mdc-chip__ripple"></span>

<span matRipple class="mat-mdc-chip-ripple"
[matRippleAnimation]="_rippleAnimation"
[matRippleDisabled]="_isRippleDisabled()"
[matRippleCentered]="_isRippleCentered"
[matRippleTrigger]="_elementRef.nativeElement"></span>

<ng-content select="mat-chip-avatar, [matChipAvatar]"></ng-content>
<div class="mdc-chip__text mdc-chip__action--primary"><ng-content></ng-content></div>
<ng-content select="mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]"></ng-content>
37 changes: 27 additions & 10 deletions src/material-experimental/mdc-chips/chip.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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()
Expand All @@ -35,19 +34,24 @@ describe('MDC-based MatChip', () => {
}));

describe('MatBasicChip', () => {

beforeEach(() => {
fixture = TestBed.createComponent(BasicChip);
fixture.detectChanges();

chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
chipNativeElement = chipDebugElement.nativeElement;
chipInstance = chipDebugElement.injector.get<MatChip>(MatChip);
chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
chipRippleInstance = chipRippleDebugElement.injector.get<MatRipple>(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', () => {
Expand All @@ -60,6 +64,8 @@ describe('MDC-based MatChip', () => {
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
chipNativeElement = chipDebugElement.nativeElement;
chipInstance = chipDebugElement.injector.get<MatChip>(MatChip);
chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
chipRippleInstance = chipRippleDebugElement.injector.get<MatRipple>(MatRipple);
testComponent = fixture.debugElement.componentInstance;
});

Expand Down Expand Up @@ -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', () => {
Expand Down Expand Up @@ -163,7 +179,7 @@ describe('MDC-based MatChip', () => {
<mat-chip [removable]="removable"
[color]="color" [disabled]="disabled"
(focus)="chipFocus($event)" (destroyed)="chipDestroy($event)"
(removed)="chipRemove($event)" [value]="value">
(removed)="chipRemove($event)" [value]="value" [disableRipple]="rippleDisabled">
{{name}}
</mat-chip>
</div>
Expand All @@ -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 = () => {};
Expand Down
Loading