diff --git a/src/components-examples/material/chips/chips-input/chips-input-example.html b/src/components-examples/material/chips/chips-input/chips-input-example.html
index ba2d4f3c7be1..37e221c4500c 100644
--- a/src/components-examples/material/chips/chips-input/chips-input-example.html
+++ b/src/components-examples/material/chips/chips-input/chips-input-example.html
@@ -4,9 +4,10 @@
+ (edited)="edit(fruit, $event)"
+ [aria-description]="'press enter to edit ' + fruit.name">
{{fruit.name}}
-
diff --git a/src/components-examples/material/chips/chips-input/chips-input-example.ts b/src/components-examples/material/chips/chips-input/chips-input-example.ts
index 38acbfb16d72..346b23d5468d 100644
--- a/src/components-examples/material/chips/chips-input/chips-input-example.ts
+++ b/src/components-examples/material/chips/chips-input/chips-input-example.ts
@@ -50,7 +50,7 @@ export class ChipsInputExample {
// Edit existing fruit
const index = this.fruits.indexOf(fruit);
- if (index > 0) {
+ if (index >= 0) {
this.fruits[index].name = value;
}
}
diff --git a/src/material/chips/chip-option.html b/src/material/chips/chip-option.html
index 3ea7c065b369..6419eeb6a294 100644
--- a/src/material/chips/chip-option.html
+++ b/src/material/chips/chip-option.html
@@ -11,6 +11,7 @@
[_allowFocusWhenDisabled]="true"
[attr.aria-selected]="ariaSelected"
[attr.aria-label]="ariaLabel"
+ [attr.aria-description]="ariaDescription"
role="option">
diff --git a/src/material/chips/chip-option.spec.ts b/src/material/chips/chip-option.spec.ts
index fed7f7eb4213..4ee1dd1ecbb3 100644
--- a/src/material/chips/chip-option.spec.ts
+++ b/src/material/chips/chip-option.spec.ts
@@ -296,6 +296,23 @@ describe('MDC-based Option Chips', () => {
});
});
+ describe('a11y', () => {
+ it('should apply `ariaLabel` and `ariaDesciption` to the element with option role', () => {
+ testComponent.ariaLabel = 'option name';
+ testComponent.ariaDescription = 'option description';
+
+ fixture.detectChanges();
+
+ const optionElement = fixture.nativeElement.querySelector('[role="option"]') as HTMLElement;
+ expect(optionElement)
+ .withContext('expected to find an element with option role')
+ .toBeTruthy();
+
+ expect(optionElement.getAttribute('aria-label')).toBe('option name');
+ expect(optionElement.getAttribute('aria-description')).toBe('option description');
+ });
+ });
+
it('should contain a focus indicator inside the text label', () => {
const label = chipNativeElement.querySelector('.mdc-evolution-chip__text-label');
expect(label?.querySelector('.mat-mdc-focus-indicator')).toBeTruthy();
@@ -310,7 +327,8 @@ describe('MDC-based Option Chips', () => {
+ (selectionChange)="chipSelectionChange($event)"
+ [aria-label]="ariaLabel" [aria-description]="ariaDescription">
{{name}}
@@ -325,6 +343,8 @@ class SingleChip {
selected: boolean = false;
selectable: boolean = true;
shouldShow: boolean = true;
+ ariaLabel: string | null = null;
+ ariaDescription: string | null = null;
chipDestroy: (event?: MatChipEvent) => void = () => {};
chipSelectionChange: (event?: MatChipSelectionChange) => void = () => {};
diff --git a/src/material/chips/chip-option.ts b/src/material/chips/chip-option.ts
index 66d9ec3b02b5..7b9bc4c13642 100644
--- a/src/material/chips/chip-option.ts
+++ b/src/material/chips/chip-option.ts
@@ -64,6 +64,7 @@ export class MatChipSelectionChange {
'[class.mat-mdc-chip-with-trailing-icon]': '_hasTrailingIcon()',
'[attr.tabindex]': 'null',
'[attr.aria-label]': 'null',
+ '[attr.aria-description]': 'null',
'[attr.role]': 'role',
'[id]': 'id',
},
diff --git a/src/material/chips/chip-row.html b/src/material/chips/chip-row.html
index bf7473656c66..ea013feaffa1 100644
--- a/src/material/chips/chip-row.html
+++ b/src/material/chips/chip-row.html
@@ -13,7 +13,8 @@
[attr.role]="editable ? 'button' : null"
[tabIndex]="tabIndex"
[disabled]="disabled"
- [attr.aria-label]="ariaLabel">
+ [attr.aria-label]="ariaLabel"
+ [attr.aria-description]="ariaDescription">
diff --git a/src/material/chips/chip-row.spec.ts b/src/material/chips/chip-row.spec.ts
index 72d3f4967cf8..20b198679ba3 100644
--- a/src/material/chips/chip-row.spec.ts
+++ b/src/material/chips/chip-row.spec.ts
@@ -332,6 +332,25 @@ describe('MDC-based Row Chips', () => {
expect(document.activeElement).not.toBe(primaryAction);
}));
});
+
+ describe('a11y', () => {
+ it('should apply `ariaLabel` and `ariaDesciption` to the primary gridcell', () => {
+ fixture.componentInstance.ariaLabel = 'chip name';
+ fixture.componentInstance.ariaDescription = 'chip description';
+
+ fixture.detectChanges();
+
+ const primaryGridCell = fixture.nativeElement.querySelector(
+ '[role="gridcell"].mdc-evolution-chip__cell--primary .mat-mdc-chip-action',
+ );
+ expect(primaryGridCell)
+ .withContext('expected to find the grid cell for the primary chip action')
+ .toBeTruthy();
+
+ expect(primaryGridCell.getAttribute('aria-label')).toBe('chip name');
+ expect(primaryGridCell.getAttribute('aria-description')).toBe('chip description');
+ });
+ });
});
});
@@ -342,7 +361,8 @@ describe('MDC-based Row Chips', () => {
+ (removed)="chipRemove($event)" (edited)="chipEdit($event)"
+ [aria-label]="ariaLabel" [aria-description]="ariaDescription">
{{name}}
x
@@ -361,6 +381,8 @@ class SingleChip {
shouldShow: boolean = true;
editable: boolean = false;
useCustomEditInput: boolean = true;
+ ariaLabel: string | null = null;
+ ariaDescription: string | null = null;
chipDestroy: (event?: MatChipEvent) => void = () => {};
chipRemove: (event?: MatChipEvent) => void = () => {};
diff --git a/src/material/chips/chip-row.ts b/src/material/chips/chip-row.ts
index a648c7c657a0..aef258f0a565 100644
--- a/src/material/chips/chip-row.ts
+++ b/src/material/chips/chip-row.ts
@@ -64,6 +64,7 @@ export interface MatChipEditedEvent extends MatChipEvent {
'[id]': 'id',
'[attr.tabindex]': 'null',
'[attr.aria-label]': 'null',
+ '[attr.aria-description]': 'null',
'[attr.role]': 'role',
'(mousedown)': '_mousedown($event)',
'(dblclick)': '_doubleclick($event)',
diff --git a/src/material/chips/chip.ts b/src/material/chips/chip.ts
index e8b6f8c4233c..66e975061eb5 100644
--- a/src/material/chips/chip.ts
+++ b/src/material/chips/chip.ts
@@ -150,6 +150,9 @@ export class MatChip
/** ARIA label for the content of the chip. */
@Input('aria-label') ariaLabel: string | null = null;
+ /** ARIA description for the content of the chip. */
+ @Input('aria-description') ariaDescription: string | null = null;
+
private _textElement!: HTMLElement;
/**
diff --git a/tools/public_api_guard/material/chips.md b/tools/public_api_guard/material/chips.md
index b67953fb9d6e..03eb3efc4efb 100644
--- a/tools/public_api_guard/material/chips.md
+++ b/tools/public_api_guard/material/chips.md
@@ -65,6 +65,7 @@ export const MAT_CHIPS_DEFAULT_OPTIONS: InjectionToken;
export class MatChip extends _MatChipMixinBase implements AfterViewInit, CanColor, CanDisableRipple, CanDisable, HasTabIndex, OnDestroy {
constructor(_changeDetectorRef: ChangeDetectorRef, elementRef: ElementRef, _ngZone: NgZone, _focusMonitor: FocusMonitor, _document: any, animationMode?: string, _globalRippleOptions?: RippleGlobalOptions | undefined, tabIndex?: string);
_animationsDisabled: boolean;
+ ariaDescription: string | null;
ariaLabel: string | null;
protected basicChipAttrName: string;
// (undocumented)
@@ -113,7 +114,7 @@ export class MatChip extends _MatChipMixinBase implements AfterViewInit, CanColo
// (undocumented)
protected _value: any;
// (undocumented)
- static ɵcmp: i0.ɵɵComponentDeclaration;
+ static ɵcmp: i0.ɵɵComponentDeclaration;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration;
}