Skip to content

Commit c268246

Browse files
authored
fix(material-experimental/mdc-list): make internal input non-interactive (#21438)
Due to how MDC's checkbox styles are set up, we always have to keep an `input` inside the `mat-list-option`, however our current setup where we only set `tabindex="-1"` on it is invalid, because the input is still interactive either through clicking on it, or by using a screen reader's forms mode. These changes completely remove the input from the accessibility model by setting it to `display: none`.
1 parent 83f2adc commit c268246

File tree

3 files changed

+13
-15
lines changed

3 files changed

+13
-15
lines changed

src/material-experimental/mdc-list/list-option.html

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,8 @@
1010

1111
<ng-template #checkbox>
1212
<div class="mdc-checkbox" [class.mdc-checkbox--disabled]="disabled">
13-
<!--
14-
Note: We stop propagation of the change event for the indicator checkbox so that
15-
no accidental change event leaks out of the list option or selection list when
16-
the checkbox is directly clicked.
17-
-->
18-
<input type="checkbox" tabindex="-1" class="mdc-checkbox__native-control"
19-
[checked]="selected" [disabled]="disabled" [attr.aria-describedby]="_optionTextId"
20-
(change)="$event.stopPropagation()" />
13+
<input type="checkbox" class="mdc-checkbox__native-control"
14+
[checked]="selected" [disabled]="disabled"/>
2115
<div class="mdc-checkbox__background">
2216
<svg class="mdc-checkbox__checkmark"
2317
viewBox="0 0 24 24">
@@ -41,7 +35,7 @@
4135
</ng-template>
4236

4337
<!-- Text -->
44-
<span class="mdc-list-item__text" #text [id]="_optionTextId">
38+
<span class="mdc-list-item__text" #text>
4539
<ng-content></ng-content>
4640
</span>
4741

src/material-experimental/mdc-list/list-option.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,13 @@
44
// The MDC-based list-option uses the MDC checkbox for the selection indicators.
55
// We need to ensure that the checkbox styles are included for the list-option.
66
@include mdc-checkbox-without-ripple($query: $mat-base-styles-query);
7+
8+
// The internal checkbox is purely decorative, but because it's an `input`, the user can still
9+
// focus it by tabbing or clicking. Furthermore, `mat-list-option` has the `option` role which
10+
// doesn't allow a nested `input`. We use `display: none` both to remove it from the tab order
11+
// and to prevent focus from reaching it through the screen reader's forms mode. Ideally we'd
12+
// remove the `input` completely, but we can't because MDC uses a `:checked` selector to
13+
// toggle the selected styles.
14+
.mat-mdc-list-option .mdc-checkbox__native-control {
15+
display: none;
16+
}

src/material-experimental/mdc-list/list-option.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ export interface SelectionList extends MatListBase {
5151
_onTouched: () => void;
5252
}
5353

54-
/** Unique id for created list options. */
55-
let uniqueId = 0;
56-
5754
@Component({
5855
selector: 'mat-list-option',
5956
exportAs: 'matListOption',
@@ -89,9 +86,6 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
8986
@ContentChildren(MatLine, {read: ElementRef, descendants: true}) lines:
9087
QueryList<ElementRef<Element>>;
9188

92-
/** Unique id for the text. Used for describing the underlying checkbox input. */
93-
_optionTextId: string = `mat-mdc-list-option-text-${uniqueId++}`;
94-
9589
/** Whether the label should appear before or after the checkbox. Defaults to 'after' */
9690
@Input() checkboxPosition: MatListOptionCheckboxPosition = 'after';
9791

0 commit comments

Comments
 (0)