Skip to content

Commit 7c33276

Browse files
authored
docs(multiple): revise and expand a11y docs (#23581)
This change updates the accessibility docs for 21 components for correctness, comprehensiveness, and clarity. I have intentionally omitted several other components either because they're being worked on by someone else or have signifcant changes pending.
1 parent 592e43e commit 7c33276

File tree

21 files changed

+378
-213
lines changed

21 files changed

+378
-213
lines changed

src/material/autocomplete/autocomplete.md

+18-8
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,12 @@ autocomplete is attached to using the `matAutocompleteOrigin` directive together
100100
```
101101

102102
### Keyboard interaction
103-
- <kbd>DOWN_ARROW</kbd>: Next option becomes active
104-
- <kbd>UP_ARROW</kbd>: Previous option becomes active
105-
- <kbd>ENTER</kbd>: Selects currently active item
106-
- <kbd>ESCAPE</kbd>: Closes the autocomplete panel
103+
- <kbd>Down Arrow</kbd>: Next option becomes active
104+
- <kbd>Up Arrow</kbd>: Previous option becomes active
105+
- <kbd>Enter</kbd>: Selects currently active item
106+
- <kbd>Escape</kbd>: Closes the autocomplete panel
107+
- <kbd>Alt + Up Arrow</kbd>: Closes the autocomplete panel
108+
- <kbd>Alt + Down Arrow</kbd>: Open the autocomplete panel if there are any matching options.
107109

108110
### Option groups
109111
`mat-option` can be collected into groups using the `mat-optgroup` element:
@@ -112,8 +114,16 @@ autocomplete is attached to using the `matAutocompleteOrigin` directive together
112114
"region":"mat-autocomplete"}) -->
113115

114116
### Accessibility
115-
The input for an autocomplete without text or labels should be given a meaningful label via
116-
`aria-label` or `aria-labelledby`.
117117

118-
The autocomplete trigger is given `role="combobox"`. The trigger sets `aria-owns` to the
119-
autocomplete's id, and sets `aria-activedescendant` to the active option's id.
118+
`MatAutocomplete` implements the ARIA combobox interaction pattern. The text input trigger specifies
119+
`role="combobox"` while the content of the pop-up applies `role="listbox"`. Because of this listbox
120+
pattern, you should _not_ put other interactive controls, such as buttons or checkboxes, inside
121+
an autocomplete option. Nesting interactive controls like this interferes with most assistive
122+
technology.
123+
124+
Always provide an accessible label for the autocomplete. This can be done
125+
via `<mat-label>` inside of `<mat-form-field>`, a native `<label>` element, the `aria-label`
126+
attribute, or the `aria-labelledby` attribute.
127+
128+
`MatAutocomplete` preserves focus on the text trigger, using `aria-activedescendant` to support
129+
navigation though the autocomplete options.

src/material/bottom-sheet/bottom-sheet.md

+42-13
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,49 @@ for `MAT_BOTTOM_SHEET_DEFAULT_OPTIONS` in your application's root module.
9696

9797

9898
### Accessibility
99-
By default, the bottom sheet has `role="dialog"` on the root element and can be labelled using the
100-
`ariaLabel` property on the `MatBottomSheetConfig`.
10199

102-
When a bottom sheet is opened, it will move focus to the first focusable element that it can find.
103-
In order to prevent users from tabbing into elements in the background, the Material bottom sheet
104-
uses a [focus trap](https://material.angular.io/cdk/a11y/overview#focustrap) to contain focus
105-
within itself. Once a bottom sheet is closed, it will return focus to the element that was focused
106-
before it was opened.
100+
`MatBottomSheet` creates modal dialogs that implement the ARIA `role="dialog"` pattern. This root
101+
dialog element should be given an accessible label via the `ariaLabel` property of
102+
`MatBottomSheetConfig`.
103+
104+
#### Keyboard interaction
105+
By default, the escape key closes `MatBottomSheet`. While you can disable this behavior by using
106+
the `disableClose` property of `MatBottomSheetConfig`, doing this breaks the expected interaction
107+
pattern for the ARIA `role="dialog"` pattern.
107108

108109
#### Focus management
109-
By default, the first tabbable element within the bottom sheet will receive focus upon open.
110-
This can be configured by setting the `cdkFocusInitial` attribute on another focusable element.
111110

112-
#### Keyboard interaction
113-
By default pressing the escape key will close the bottom sheet. While this behavior can
114-
be turned off via the `disableClose` option, users should generally avoid doing so
115-
as it breaks the expected interaction pattern for screen-reader users.
111+
When opened, `MatBottomSheet` traps browser focus such that it cannot escape the root
112+
`role="dialog"` element. By default, the first tabbable element in the bottom sheet receives focus.
113+
You can customize which element receives focus with the `autoFocus` property of
114+
`MatBottomSheetConfig`, which supports the following values.
115+
116+
| Value | Behavior |
117+
|------------------|--------------------------------------------------------------------------|
118+
| `first-tabbable` | Focus the first tabbable element. This is the default setting. |
119+
| `first-header` | Focus the first header element (`role="heading"`, `h1` through `h6`) |
120+
| `dialog` | Focus the root `role="dialog"` element. |
121+
| Any CSS selector | Focus the first element matching the given selector. |
122+
123+
While the default setting applies the best behavior for most applications, special cases may benefit
124+
from these alternatives. Always test your application to verify the behavior that works best for
125+
your users.
126+
127+
#### Focus restoration
128+
129+
When closed, `MatBottomSheet` restores focus to the element that previously held focus when the
130+
bottom sheet opened. However, if that previously focused element no longer exists, you must
131+
add additional handling to return focus to an element that makes sense for the user's workflow.
132+
Opening a bottom sheet from a menu is one common pattern that causes this situation. The menu
133+
closes upon clicking an item, thus the focused menu item is no longer in the DOM when the bottom
134+
sheet attempts to restore focus.
135+
136+
You can add handling for this situation with the `afterDismissed()` observable from
137+
`MatBottomSheetRef`.
138+
139+
```typescript
140+
const bottomSheetRef = bottomSheet.open(FileTypeChooser);
141+
bottomSheetRef.afterDismissed().subscribe(() => {
142+
// Restore focus to an appropriate element for the user's workflow here.
143+
});
144+
```

src/material/button-toggle/button-toggle.md

+19-12
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,24 @@ be configured globally using the `MAT_BUTTON_TOGGLE_DEFAULT_OPTIONS` injection t
2828
`<mat-button-toggle-group>` is compatible with `@angular/forms` and supports both `FormsModule`
2929
and `ReactiveFormsModule`.
3030

31-
### Accessibility
32-
The button-toggles internally use native `button` elements with `aria-pressed` to convey
33-
their toggled state. The button-toggle-group surrounding the individual buttons applies
34-
`role="group"` to convey the association between the individual toggles.
35-
36-
For button toggles containing only icons, each button toggle should be given a meaningful label via
37-
`aria-label` or `aria-labelledby`.
38-
39-
For button toggle groups, each group should be given a meaningful label via `aria-label` or
40-
`aria-labelledby`.
41-
42-
4331
### Orientation
4432
The button-toggles can be rendered in a vertical orientation by adding the `vertical` attribute.
33+
34+
### Accessibility
35+
`MatButtonToggle` internally uses native `button` elements with `aria-pressed` to convey toggle
36+
state. If a toggle contains only an icon, you should specify a meaningful label via `aria-label`
37+
or `aria-labelledby`. For dynamic labels, `MatButtonToggle` provides input properties for binding
38+
`aria-label` and `aria-labelledby`. This means that you should not use the `attr.` prefix when
39+
binding these properties, as demonstrated below.
40+
41+
```html
42+
<mat-button-toggle [aria-label]="alertsEnabled ? 'Disable alerts' : 'Enable alerts'">
43+
<mat-icon>notifications</mat-icon>
44+
</mat-button-toggle>
45+
```
46+
47+
The `MatButtonToggleGroup` surrounding the individual buttons applies
48+
`role="group"` to convey the association between the individual toggles. Each
49+
`<mat-button-toggle-group>` element should be given a label with `aria-label` or `aria-labelledby`
50+
that communicates the collective meaning of all toggles. For example, if you have toggles for
51+
"Bold", "Italic", and "Underline", you might label the parent group "Font styles".

src/material/card/card.md

+21-17
Original file line numberDiff line numberDiff line change
@@ -44,32 +44,36 @@ This element can contain:
4444
* `<img mat-card-lg-image>`
4545

4646
### Accessibility
47-
Cards can be used in a wide variety of scenarios and can contain many different types of content.
48-
Due to this dynamic nature, the appropriate accessibility treatment depends on how `<mat-card>` is
49-
used.
47+
48+
Cards serve a wide variety of scenarios and may contain many different types of content.
49+
Due to this flexible nature, the appropriate accessibility treatment depends on how you use
50+
`<mat-card>`.
5051

5152
#### Group, region, and landmarks
53+
5254
There are several ARIA roles that communicate that a portion of the UI represents some semantically
53-
meaningful whole. Depending on what the content of the card means to your application,
54-
[`role="group"`][0], [`role="region"`][1], or [one of the landmark roles][2] should typically be
55-
applied to the `<mat-card>` element.
55+
meaningful whole. Depending on what the content of the card means to your application, you can apply
56+
one of [`role="group"`][role-group], [`role="region"`][role-region], or
57+
[one of the landmark roles][aria-landmarks] to the `<mat-card>` element.
5658

57-
A role is not necessary when the card is used as a purely decorative container that does not
59+
You do not need to apply a role when using a card as a purely decorative container that does not
5860
convey a meaningful grouping of related content for a single subject. In these cases, the content
5961
of the card should follow standard practices for document content.
6062

61-
6263
#### Focus
63-
Depending on how cards are used, it may be appropriate to apply a `tabindex` to the `<mat-card>`
64-
element. If cards are a primary mechanism through which user interacts with the application,
65-
`tabindex="0"` is appropriate. If attention can be sent to the card, but it's not part of the
66-
document flow, `tabindex="-1"` is appropriate.
6764

68-
If the card acts as a purely decorative container, it does not need to be tabbable. In this case,
69-
the card content should follow normal best practices for tab order.
65+
Depending on how cards are used, it may be appropriate to apply a `tabindex` to the `<mat-card>`
66+
element.
7067

68+
* If cards are a primary mechanism through which user interacts with the application, `tabindex="0"`
69+
may be appropriate.
70+
* If attention can be sent to the card, but it's not part of the document flow, `tabindex="-1"` may
71+
be appropriate.
72+
* If the card acts as a purely decorative container, it does not need to be tabbable. In this case,
73+
the card content should follow normal best practices for tab order.
7174

75+
Always test your application to verify the behavior that works best for your users.
7276

73-
[0]: https://www.w3.org/TR/wai-aria/#group
74-
[1]: https://www.w3.org/TR/wai-aria/#region
75-
[2]: https://www.w3.org/TR/wai-aria/#landmark
77+
[role-group]: https://www.w3.org/TR/wai-aria/#group
78+
[role-region]: https://www.w3.org/TR/wai-aria/#region
79+
[aria-landmarks]: https://www.w3.org/TR/wai-aria/#landmark

src/material/checkbox/checkbox.md

+13-4
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,18 @@ The color of a `<mat-checkbox>` can be changed by using the `color` property. By
5656
use the theme's accent color. This can be changed to `'primary'` or `'warn'`.
5757

5858
### Accessibility
59-
The `<mat-checkbox>` uses an internal `<input type="checkbox">` to provide an accessible experience.
59+
60+
`MatCheckbox` uses an internal `<input type="checkbox">` to provide an accessible experience.
6061
This internal checkbox receives focus and is automatically labelled by the text content of the
61-
`<mat-checkbox>` element.
62+
`<mat-checkbox>` element. Avoid adding other interactive controls into the content of
63+
`<mat-checkbox>`, as this degrades the experience for users of assistive technology.
64+
65+
Always provide an accessible label via `aria-label` or `aria-labelledby` for checkboxes without
66+
descriptive text content. For dynamic labels, `MatCheckbox` provides input properties for binding
67+
`aria-label` and `aria-labelledby`. This means that you should not use the `attr.` prefix when
68+
binding these properties, as demonstrated below.
6269

63-
Checkboxes without text or labels should be given a meaningful label via `aria-label` or
64-
`aria-labelledby`.
70+
```html
71+
<mat-checkbox [aria-label]="isSubscribedToEmailsMessage">
72+
</mat-checkbox>
73+
```

src/material/datepicker/datepicker.md

+56-48
Original file line numberDiff line numberDiff line change
@@ -562,72 +562,80 @@ value can be anything that is accepted by `ngClass`.
562562

563563
### Accessibility
564564

565-
The `MatDatepickerInput` and `MatDatepickerToggle` directives add the `aria-haspopup` attribute to
566-
the native input and toggle button elements respectively, and they trigger a calendar dialog with
567-
`role="dialog"`.
565+
The `MatDatepicker` pop-up uses the `role="dialog"` interaction pattern. This dialog then contains
566+
multiple controls, the most prominent being the calendar itself. This calendar implements the
567+
`role="grid"` interaction pattern.
568568

569-
`MatDatepickerIntl` includes strings that are used for `aria-label`s. The datepicker input
570-
should have a placeholder or be given a meaningful label via `aria-label`, `aria-labelledby` or
569+
The `MatDatepickerInput` and `MatDatepickerToggle` directives both apply the `aria-haspopup`
570+
attribute to the native input and button elements, respectively.
571+
572+
`MatDatepickerIntl` includes strings that are used for `aria-label` attributes. Always provide
573+
the datepicker text input a meaningful label via `<mat-label>`, `aria-label`, `aria-labelledby` or
571574
`MatDatepickerIntl`.
572575

576+
`MatDatepickerInput` adds <kbd>>Alt</kbd> + <kbd>Down Arrow</kbd> as a keyboard short to open the
577+
datepicker pop-up. However, ChromeOS intercepts this key combination at the OS level such that the
578+
browser only receives a `PageDown` key event. Because of this behavior, you should always include an
579+
additional means of opening the pop-up, such as `MatDatepickerToggle`.
580+
573581
#### Keyboard interaction
574582

575583
The datepicker supports the following keyboard shortcuts:
576584

577-
| Shortcut | Action |
578-
|----------------------|-------------------------------------------|
579-
| `ALT` + `DOWN_ARROW` | Open the calendar pop-up |
580-
| `ESCAPE` | Close the calendar pop-up |
585+
| Shortcut | Action |
586+
|----------------------------------------|----------------------------|
587+
| <kbd>ALT</kbd> + <kbd>DOWN_ARROW</kbd> | Open the calendar pop-up |
588+
| <kbd>ESCAPE</kbd> | Close the calendar pop-up |
581589

582590

583591
In month view:
584592

585-
| Shortcut | Action |
586-
|----------------------|-------------------------------------------|
587-
| `LEFT_ARROW` | Go to previous day |
588-
| `RIGHT_ARROW` | Go to next day |
589-
| `UP_ARROW` | Go to same day in the previous week |
590-
| `DOWN_ARROW` | Go to same day in the next week |
591-
| `HOME` | Go to the first day of the month |
592-
| `END` | Go to the last day of the month |
593-
| `PAGE_UP` | Go to the same day in the previous month |
594-
| `ALT` + `PAGE_UP` | Go to the same day in the previous year |
595-
| `PAGE_DOWN` | Go to the same day in the next month |
596-
| `ALT` + `PAGE_DOWN` | Go to the same day in the next year |
597-
| `ENTER` | Select current date |
593+
| Shortcut | Action |
594+
|---------------------------------------|------------------------------------------|
595+
| <kbd>LEFT_ARROW</kbd> | Go to previous day |
596+
| <kbd>RIGHT_ARROW</kbd> | Go to next day |
597+
| <kbd>UP_ARROW</kbd> | Go to same day in the previous week |
598+
| <kbd>DOWN_ARROW</kbd> | Go to same day in the next week |
599+
| <kbd>HOME</kbd> | Go to the first day of the month |
600+
| <kbd>END</kbd> | Go to the last day of the month |
601+
| <kbd>PAGE_UP</kbd> | Go to the same day in the previous month |
602+
| <kbd>ALT</kbd> + <kbd>PAGE_UP</kbd> | Go to the same day in the previous year |
603+
| <kbd>PAGE_DOWN</kbd> | Go to the same day in the next month |
604+
| <kbd>ALT</kbd> + <kbd>PAGE_DOWN</kbd> | Go to the same day in the next year |
605+
| <kbd>ENTER</kbd> | Select current date |
598606

599607

600608
In year view:
601609

602-
| Shortcut | Action |
603-
|----------------------|-------------------------------------------|
604-
| `LEFT_ARROW` | Go to previous month |
605-
| `RIGHT_ARROW` | Go to next month |
606-
| `UP_ARROW` | Go up a row (back 4 months) |
607-
| `DOWN_ARROW` | Go down a row (forward 4 months) |
608-
| `HOME` | Go to the first month of the year |
609-
| `END` | Go to the last month of the year |
610-
| `PAGE_UP` | Go to the same month in the previous year |
611-
| `ALT` + `PAGE_UP` | Go to the same month 10 years back |
612-
| `PAGE_DOWN` | Go to the same month in the next year |
613-
| `ALT` + `PAGE_DOWN` | Go to the same month 10 years forward |
614-
| `ENTER` | Select current month |
610+
| Shortcut | Action |
611+
|---------------------------------------|-------------------------------------------|
612+
| <kbd>LEFT_ARROW</kbd> | Go to previous month |
613+
| <kbd>RIGHT_ARROW</kbd> | Go to next month |
614+
| <kbd>UP_ARROW</kbd> | Go up a row (back 4 months) |
615+
| <kbd>DOWN_ARROW</kbd> | Go down a row (forward 4 months) |
616+
| <kbd>HOME</kbd> | Go to the first month of the year |
617+
| <kbd>END</kbd> | Go to the last month of the year |
618+
| <kbd>PAGE_UP</kbd> | Go to the same month in the previous year |
619+
| <kbd>ALT</kbd> + <kbd>PAGE_UP</kbd> | Go to the same month 10 years back |
620+
| <kbd>PAGE_DOWN</kbd> | Go to the same month in the next year |
621+
| <kbd>ALT</kbd> + <kbd>PAGE_DOWN</kbd> | Go to the same month 10 years forward |
622+
| <kbd>ENTER</kbd> | Select current month |
615623

616624
In multi-year view:
617625

618-
| Shortcut | Action |
619-
|----------------------|-------------------------------------------|
620-
| `LEFT_ARROW` | Go to previous year |
621-
| `RIGHT_ARROW` | Go to next year |
622-
| `UP_ARROW` | Go up a row (back 4 years) |
623-
| `DOWN_ARROW` | Go down a row (forward 4 years) |
624-
| `HOME` | Go to the first year in the current range |
625-
| `END` | Go to the last year in the current range |
626-
| `PAGE_UP` | Go back 24 years |
627-
| `ALT` + `PAGE_UP` | Go back 240 years |
628-
| `PAGE_DOWN` | Go forward 24 years |
629-
| `ALT` + `PAGE_DOWN` | Go forward 240 years |
630-
| `ENTER` | Select current year |
626+
| Shortcut | Action |
627+
|---------------------------------------|-------------------------------------------|
628+
| <kbd>LEFT_ARROW</kbd> | Go to previous year |
629+
| <kbd>RIGHT_ARROW</kbd> | Go to next year |
630+
| <kbd>UP_ARROW</kbd> | Go up a row (back 4 years) |
631+
| <kbd>DOWN_ARROW</kbd> | Go down a row (forward 4 years) |
632+
| <kbd>HOME</kbd> | Go to the first year in the current range |
633+
| <kbd>END</kbd> | Go to the last year in the current range |
634+
| <kbd>PAGE_UP</kbd> | Go back 24 years |
635+
| <kbd>ALT</kbd> + <kbd>PAGE_UP</kbd> | Go back 240 years |
636+
| <kbd>PAGE_DOWN</kbd> | Go forward 24 years |
637+
| <kbd>ALT</kbd> + <kbd>PAGE_DOWN</kbd> | Go forward 240 years |
638+
| <kbd>ENTER</kbd> | Select current year |
631639

632640
### Troubleshooting
633641

0 commit comments

Comments
 (0)