File tree 7 files changed +67
-7
lines changed
7 files changed +67
-7
lines changed Original file line number Diff line number Diff line change 11
11
[_allowFocusWhenDisabled] ="true "
12
12
[attr.aria-selected] ="ariaSelected "
13
13
[attr.aria-label] ="ariaLabel "
14
- [attr.aria-description ] ="ariaDescription "
14
+ [attr.aria-describedby ] ="_ariaDescriptionId "
15
15
role ="option ">
16
16
< span class ="mdc-evolution-chip__graphic mat-mdc-chip-graphic ">
17
17
< ng-content select ="mat-chip-avatar, [matChipAvatar] "> </ ng-content >
34
34
*ngIf ="_hasTrailingIcon() ">
35
35
< ng-content select ="mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon] "> </ ng-content >
36
36
</ span >
37
+
38
+ < span class ="cdk-visually-hidden " [id] ="_ariaDescriptionId "> {{ariaDescription}}</ span >
Original file line number Diff line number Diff line change @@ -308,8 +308,28 @@ describe('MDC-based Option Chips', () => {
308
308
. withContext ( 'expected to find an element with option role' )
309
309
. toBeTruthy ( ) ;
310
310
311
- expect ( optionElement . getAttribute ( 'aria-label' ) ) . toBe ( 'option name' ) ;
312
- expect ( optionElement . getAttribute ( 'aria-description' ) ) . toBe ( 'option description' ) ;
311
+ expect ( optionElement . getAttribute ( 'aria-label' ) ) . toMatch ( / o p t i o n n a m e / i) ;
312
+
313
+ const optionElementDescribedBy = optionElement ! . getAttribute ( 'aria-describedby' ) ;
314
+ expect ( optionElementDescribedBy )
315
+ . withContext ( 'expected primary grid cell to have a non-empty aria-describedby attribute' )
316
+ . toBeTruthy ( ) ;
317
+
318
+ const optionElementDescriptions = Array . from (
319
+ ( fixture . nativeElement as HTMLElement ) . querySelectorAll (
320
+ optionElementDescribedBy !
321
+ . split ( / \s + / g)
322
+ . map ( x => `#${ x } ` )
323
+ . join ( ',' ) ,
324
+ ) ,
325
+ ) ;
326
+
327
+ const optionElementDescription = optionElementDescriptions
328
+ . map ( x => x . textContent ?. trim ( ) )
329
+ . join ( ' ' )
330
+ . trim ( ) ;
331
+
332
+ expect ( optionElementDescription ) . toMatch ( / o p t i o n d e s c r i p t i o n / i) ;
313
333
} ) ;
314
334
} ) ;
315
335
Original file line number Diff line number Diff line change @@ -31,6 +31,8 @@ export class MatChipSelectionChange {
31
31
) { }
32
32
}
33
33
34
+ let id = 1 ;
35
+
34
36
/**
35
37
* An extension of the MatChip component that supports chip selection. Used with MatChipListbox.
36
38
*
@@ -178,4 +180,7 @@ export class MatChipOption extends MatChip implements OnInit {
178
180
this . _changeDetectorRef . markForCheck ( ) ;
179
181
}
180
182
}
183
+
184
+ /** Id of a span that contains this chip's aria description. @docs-private */
185
+ _ariaDescriptionId = `chip-option-${ id ++ } -aria-description` ;
181
186
}
Original file line number Diff line number Diff line change 14
14
[tabIndex] ="tabIndex "
15
15
[disabled] ="disabled "
16
16
[attr.aria-label] ="ariaLabel "
17
- [attr.aria-description ] ="ariaDescription ">
17
+ [attr.aria-describedby ] ="_ariaDescriptionId ">
18
18
< span class ="mdc-evolution-chip__graphic mat-mdc-chip-graphic " *ngIf ="leadingIcon ">
19
19
< ng-content select ="mat-chip-avatar, [matChipAvatar] "> </ ng-content >
20
20
</ span >
38
38
*ngIf ="_hasTrailingIcon() ">
39
39
< ng-content select ="mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon] "> </ ng-content >
40
40
</ span >
41
+
42
+ < span class ="cdk-visually-hidden " [id] ="_ariaDescriptionId "> {{ariaDescription}}</ span >
Original file line number Diff line number Diff line change @@ -340,15 +340,35 @@ describe('MDC-based Row Chips', () => {
340
340
341
341
fixture . detectChanges ( ) ;
342
342
343
- const primaryGridCell = fixture . nativeElement . querySelector (
343
+ const primaryGridCell = ( fixture . nativeElement as HTMLElement ) . querySelector (
344
344
'[role="gridcell"].mdc-evolution-chip__cell--primary .mat-mdc-chip-action' ,
345
345
) ;
346
346
expect ( primaryGridCell )
347
347
. withContext ( 'expected to find the grid cell for the primary chip action' )
348
348
. toBeTruthy ( ) ;
349
349
350
- expect ( primaryGridCell . getAttribute ( 'aria-label' ) ) . toBe ( 'chip name' ) ;
351
- expect ( primaryGridCell . getAttribute ( 'aria-description' ) ) . toBe ( 'chip description' ) ;
350
+ expect ( primaryGridCell ! . getAttribute ( 'aria-label' ) ) . toMatch ( / c h i p n a m e / i) ;
351
+
352
+ const primaryGridCellDescribedBy = primaryGridCell ! . getAttribute ( 'aria-describedby' ) ;
353
+ expect ( primaryGridCellDescribedBy )
354
+ . withContext ( 'expected primary grid cell to have a non-empty aria-describedby attribute' )
355
+ . toBeTruthy ( ) ;
356
+
357
+ const primaryGridCellDescriptions = Array . from (
358
+ ( fixture . nativeElement as HTMLElement ) . querySelectorAll (
359
+ primaryGridCellDescribedBy !
360
+ . split ( / \s + / g)
361
+ . map ( x => `#${ x } ` )
362
+ . join ( ',' ) ,
363
+ ) ,
364
+ ) ;
365
+
366
+ const primaryGridCellDescription = primaryGridCellDescriptions
367
+ . map ( x => x . textContent ?. trim ( ) )
368
+ . join ( ' ' )
369
+ . trim ( ) ;
370
+
371
+ expect ( primaryGridCellDescription ) . toMatch ( / c h i p d e s c r i p t i o n / i) ;
352
372
} ) ;
353
373
} ) ;
354
374
} ) ;
Original file line number Diff line number Diff line change @@ -33,6 +33,8 @@ import {MatChipEditInput} from './chip-edit-input';
33
33
import { takeUntil } from 'rxjs/operators' ;
34
34
import { MAT_CHIP } from './tokens' ;
35
35
36
+ let id = 1 ;
37
+
36
38
/** Represents an event fired on an individual `mat-chip` when it is edited. */
37
39
export interface MatChipEditedEvent extends MatChipEvent {
38
40
/** The final edit value. */
@@ -212,4 +214,7 @@ export class MatChipRow extends MatChip implements AfterViewInit {
212
214
private _getEditInput ( ) : MatChipEditInput {
213
215
return this . contentEditInput || this . defaultEditInput ! ;
214
216
}
217
+
218
+ /** Id of a span that contains this chip's aria description. @docs-private */
219
+ _ariaDescriptionId = `chip-row-${ id ++ } -aria-description` ;
215
220
}
Original file line number Diff line number Diff line change @@ -147,9 +147,15 @@ export class MatChip
147
147
/** A unique id for the chip. If none is supplied, it will be auto-generated. */
148
148
@Input ( ) id : string = `mat-mdc-chip-${ uid ++ } ` ;
149
149
150
+ // TODO(#26104): Consider deprecating and using `_computeAriaAccessibleName` instead.
151
+ // `ariaLabel` may be unnecessary, and `_computeAriaAccessibleName` only supports
152
+ // datepicker's use case.
150
153
/** ARIA label for the content of the chip. */
151
154
@Input ( 'aria-label' ) ariaLabel : string | null = null ;
152
155
156
+ // TODO(#26104): Consider deprecating and using `_computeAriaAccessibleName` instead.
157
+ // `ariaDescription` may be unnecessary, and `_computeAriaAccessibleName` only supports
158
+ // datepicker's use case.
153
159
/** ARIA description for the content of the chip. */
154
160
@Input ( 'aria-description' ) ariaDescription : string | null = null ;
155
161
You can’t perform that action at this time.
0 commit comments