Skip to content

docs(multiple): revise and expand a11y docs #23581

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

Merged
merged 1 commit into from
Sep 16, 2021
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
26 changes: 18 additions & 8 deletions src/material/autocomplete/autocomplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ autocomplete is attached to using the `matAutocompleteOrigin` directive together
```

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

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

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

The autocomplete trigger is given `role="combobox"`. The trigger sets `aria-owns` to the
autocomplete's id, and sets `aria-activedescendant` to the active option's id.
`MatAutocomplete` implements the ARIA combobox interaction pattern. The text input trigger specifies
`role="combobox"` while the content of the pop-up applies `role="listbox"`. Because of this listbox
pattern, you should _not_ put other interactive controls, such as buttons or checkboxes, inside
an autocomplete option. Nesting interactive controls like this interferes with most assistive
technology.

Always provide an accessible label for the autocomplete. This can be done
via `<mat-label>` inside of `<mat-form-field>`, a native `<label>` element, the `aria-label`
attribute, or the `aria-labelledby` attribute.

`MatAutocomplete` preserves focus on the text trigger, using `aria-activedescendant` to support
navigation though the autocomplete options.
55 changes: 42 additions & 13 deletions src/material/bottom-sheet/bottom-sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,49 @@ for `MAT_BOTTOM_SHEET_DEFAULT_OPTIONS` in your application's root module.


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

When a bottom sheet is opened, it will move focus to the first focusable element that it can find.
In order to prevent users from tabbing into elements in the background, the Material bottom sheet
uses a [focus trap](https://material.angular.io/cdk/a11y/overview#focustrap) to contain focus
within itself. Once a bottom sheet is closed, it will return focus to the element that was focused
before it was opened.
`MatBottomSheet` creates modal dialogs that implement the ARIA `role="dialog"` pattern. This root
dialog element should be given an accessible label via the `ariaLabel` property of
`MatBottomSheetConfig`.

#### Keyboard interaction
By default, the escape key closes `MatBottomSheet`. While you can disable this behavior by using
the `disableClose` property of `MatBottomSheetConfig`, doing this breaks the expected interaction
pattern for the ARIA `role="dialog"` pattern.

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

#### Keyboard interaction
By default pressing the escape key will close the bottom sheet. While this behavior can
be turned off via the `disableClose` option, users should generally avoid doing so
as it breaks the expected interaction pattern for screen-reader users.
When opened, `MatBottomSheet` traps browser focus such that it cannot escape the root
`role="dialog"` element. By default, the first tabbable element in the bottom sheet receives focus.
You can customize which element receives focus with the `autoFocus` property of
`MatBottomSheetConfig`, which supports the following values.

| Value | Behavior |
|------------------|--------------------------------------------------------------------------|
| `first-tabbable` | Focus the first tabbable element. This is the default setting. |
| `first-header` | Focus the first header element (`role="heading"`, `h1` through `h6`) |
| `dialog` | Focus the root `role="dialog"` element. |
| Any CSS selector | Focus the first element matching the given selector. |

While the default setting applies the best behavior for most applications, special cases may benefit
from these alternatives. Always test your application to verify the behavior that works best for
your users.

#### Focus restoration

When closed, `MatBottomSheet` restores focus to the element that previously held focus when the
bottom sheet opened. However, if that previously focused element no longer exists, you must
add additional handling to return focus to an element that makes sense for the user's workflow.
Opening a bottom sheet from a menu is one common pattern that causes this situation. The menu
closes upon clicking an item, thus the focused menu item is no longer in the DOM when the bottom
sheet attempts to restore focus.

You can add handling for this situation with the `afterDismissed()` observable from
`MatBottomSheetRef`.

```typescript
const bottomSheetRef = bottomSheet.open(FileTypeChooser);
bottomSheetRef.afterDismissed().subscribe(() => {
// Restore focus to an appropriate element for the user's workflow here.
});
```
31 changes: 19 additions & 12 deletions src/material/button-toggle/button-toggle.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,24 @@ be configured globally using the `MAT_BUTTON_TOGGLE_DEFAULT_OPTIONS` injection t
`<mat-button-toggle-group>` is compatible with `@angular/forms` and supports both `FormsModule`
and `ReactiveFormsModule`.

### Accessibility
The button-toggles internally use native `button` elements with `aria-pressed` to convey
their toggled state. The button-toggle-group surrounding the individual buttons applies
`role="group"` to convey the association between the individual toggles.

For button toggles containing only icons, each button toggle should be given a meaningful label via
`aria-label` or `aria-labelledby`.

For button toggle groups, each group should be given a meaningful label via `aria-label` or
`aria-labelledby`.


### Orientation
The button-toggles can be rendered in a vertical orientation by adding the `vertical` attribute.

### Accessibility
`MatButtonToggle` internally uses native `button` elements with `aria-pressed` to convey toggle
state. If a toggle contains only an icon, you should specify a meaningful label via `aria-label`
or `aria-labelledby`. For dynamic labels, `MatButtonToggle` provides input properties for binding
`aria-label` and `aria-labelledby`. This means that you should not use the `attr.` prefix when
binding these properties, as demonstrated below.

```html
<mat-button-toggle [aria-label]="alertsEnabled ? 'Disable alerts' : 'Enable alerts'">
<mat-icon>notifications</mat-icon>
</mat-button-toggle>
```

The `MatButtonToggleGroup` surrounding the individual buttons applies
`role="group"` to convey the association between the individual toggles. Each
`<mat-button-toggle-group>` element should be given a label with `aria-label` or `aria-labelledby`
that communicates the collective meaning of all toggles. For example, if you have toggles for
"Bold", "Italic", and "Underline", you might label the parent group "Font styles".
38 changes: 21 additions & 17 deletions src/material/card/card.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,36 @@ This element can contain:
* `<img mat-card-lg-image>`

### Accessibility
Cards can be used in a wide variety of scenarios and can contain many different types of content.
Due to this dynamic nature, the appropriate accessibility treatment depends on how `<mat-card>` is
used.

Cards serve a wide variety of scenarios and may contain many different types of content.
Due to this flexible nature, the appropriate accessibility treatment depends on how you use
`<mat-card>`.

#### Group, region, and landmarks

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

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


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

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

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

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

[0]: https://www.w3.org/TR/wai-aria/#group
[1]: https://www.w3.org/TR/wai-aria/#region
[2]: https://www.w3.org/TR/wai-aria/#landmark
[role-group]: https://www.w3.org/TR/wai-aria/#group
[role-region]: https://www.w3.org/TR/wai-aria/#region
[aria-landmarks]: https://www.w3.org/TR/wai-aria/#landmark
17 changes: 13 additions & 4 deletions src/material/checkbox/checkbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,18 @@ The color of a `<mat-checkbox>` can be changed by using the `color` property. By
use the theme's accent color. This can be changed to `'primary'` or `'warn'`.

### Accessibility
The `<mat-checkbox>` uses an internal `<input type="checkbox">` to provide an accessible experience.

`MatCheckbox` uses an internal `<input type="checkbox">` to provide an accessible experience.
This internal checkbox receives focus and is automatically labelled by the text content of the
`<mat-checkbox>` element.
`<mat-checkbox>` element. Avoid adding other interactive controls into the content of
`<mat-checkbox>`, as this degrades the experience for users of assistive technology.

Always provide an accessible label via `aria-label` or `aria-labelledby` for checkboxes without
descriptive text content. For dynamic labels, `MatCheckbox` provides input properties for binding
`aria-label` and `aria-labelledby`. This means that you should not use the `attr.` prefix when
binding these properties, as demonstrated below.

Checkboxes without text or labels should be given a meaningful label via `aria-label` or
`aria-labelledby`.
```html
<mat-checkbox [aria-label]="isSubscribedToEmailsMessage">
</mat-checkbox>
```
104 changes: 56 additions & 48 deletions src/material/datepicker/datepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,72 +562,80 @@ value can be anything that is accepted by `ngClass`.

### Accessibility

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

`MatDatepickerIntl` includes strings that are used for `aria-label`s. The datepicker input
should have a placeholder or be given a meaningful label via `aria-label`, `aria-labelledby` or
The `MatDatepickerInput` and `MatDatepickerToggle` directives both apply the `aria-haspopup`
attribute to the native input and button elements, respectively.

`MatDatepickerIntl` includes strings that are used for `aria-label` attributes. Always provide
the datepicker text input a meaningful label via `<mat-label>`, `aria-label`, `aria-labelledby` or
`MatDatepickerIntl`.

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

#### Keyboard interaction

The datepicker supports the following keyboard shortcuts:

| Shortcut | Action |
|----------------------|-------------------------------------------|
| `ALT` + `DOWN_ARROW` | Open the calendar pop-up |
| `ESCAPE` | Close the calendar pop-up |
| Shortcut | Action |
|----------------------------------------|----------------------------|
| <kbd>ALT</kbd> + <kbd>DOWN_ARROW</kbd> | Open the calendar pop-up |
| <kbd>ESCAPE</kbd> | Close the calendar pop-up |


In month view:

| Shortcut | Action |
|----------------------|-------------------------------------------|
| `LEFT_ARROW` | Go to previous day |
| `RIGHT_ARROW` | Go to next day |
| `UP_ARROW` | Go to same day in the previous week |
| `DOWN_ARROW` | Go to same day in the next week |
| `HOME` | Go to the first day of the month |
| `END` | Go to the last day of the month |
| `PAGE_UP` | Go to the same day in the previous month |
| `ALT` + `PAGE_UP` | Go to the same day in the previous year |
| `PAGE_DOWN` | Go to the same day in the next month |
| `ALT` + `PAGE_DOWN` | Go to the same day in the next year |
| `ENTER` | Select current date |
| Shortcut | Action |
|---------------------------------------|------------------------------------------|
| <kbd>LEFT_ARROW</kbd> | Go to previous day |
| <kbd>RIGHT_ARROW</kbd> | Go to next day |
| <kbd>UP_ARROW</kbd> | Go to same day in the previous week |
| <kbd>DOWN_ARROW</kbd> | Go to same day in the next week |
| <kbd>HOME</kbd> | Go to the first day of the month |
| <kbd>END</kbd> | Go to the last day of the month |
| <kbd>PAGE_UP</kbd> | Go to the same day in the previous month |
| <kbd>ALT</kbd> + <kbd>PAGE_UP</kbd> | Go to the same day in the previous year |
| <kbd>PAGE_DOWN</kbd> | Go to the same day in the next month |
| <kbd>ALT</kbd> + <kbd>PAGE_DOWN</kbd> | Go to the same day in the next year |
| <kbd>ENTER</kbd> | Select current date |


In year view:

| Shortcut | Action |
|----------------------|-------------------------------------------|
| `LEFT_ARROW` | Go to previous month |
| `RIGHT_ARROW` | Go to next month |
| `UP_ARROW` | Go up a row (back 4 months) |
| `DOWN_ARROW` | Go down a row (forward 4 months) |
| `HOME` | Go to the first month of the year |
| `END` | Go to the last month of the year |
| `PAGE_UP` | Go to the same month in the previous year |
| `ALT` + `PAGE_UP` | Go to the same month 10 years back |
| `PAGE_DOWN` | Go to the same month in the next year |
| `ALT` + `PAGE_DOWN` | Go to the same month 10 years forward |
| `ENTER` | Select current month |
| Shortcut | Action |
|---------------------------------------|-------------------------------------------|
| <kbd>LEFT_ARROW</kbd> | Go to previous month |
| <kbd>RIGHT_ARROW</kbd> | Go to next month |
| <kbd>UP_ARROW</kbd> | Go up a row (back 4 months) |
| <kbd>DOWN_ARROW</kbd> | Go down a row (forward 4 months) |
| <kbd>HOME</kbd> | Go to the first month of the year |
| <kbd>END</kbd> | Go to the last month of the year |
| <kbd>PAGE_UP</kbd> | Go to the same month in the previous year |
| <kbd>ALT</kbd> + <kbd>PAGE_UP</kbd> | Go to the same month 10 years back |
| <kbd>PAGE_DOWN</kbd> | Go to the same month in the next year |
| <kbd>ALT</kbd> + <kbd>PAGE_DOWN</kbd> | Go to the same month 10 years forward |
| <kbd>ENTER</kbd> | Select current month |

In multi-year view:

| Shortcut | Action |
|----------------------|-------------------------------------------|
| `LEFT_ARROW` | Go to previous year |
| `RIGHT_ARROW` | Go to next year |
| `UP_ARROW` | Go up a row (back 4 years) |
| `DOWN_ARROW` | Go down a row (forward 4 years) |
| `HOME` | Go to the first year in the current range |
| `END` | Go to the last year in the current range |
| `PAGE_UP` | Go back 24 years |
| `ALT` + `PAGE_UP` | Go back 240 years |
| `PAGE_DOWN` | Go forward 24 years |
| `ALT` + `PAGE_DOWN` | Go forward 240 years |
| `ENTER` | Select current year |
| Shortcut | Action |
|---------------------------------------|-------------------------------------------|
| <kbd>LEFT_ARROW</kbd> | Go to previous year |
| <kbd>RIGHT_ARROW</kbd> | Go to next year |
| <kbd>UP_ARROW</kbd> | Go up a row (back 4 years) |
| <kbd>DOWN_ARROW</kbd> | Go down a row (forward 4 years) |
| <kbd>HOME</kbd> | Go to the first year in the current range |
| <kbd>END</kbd> | Go to the last year in the current range |
| <kbd>PAGE_UP</kbd> | Go back 24 years |
| <kbd>ALT</kbd> + <kbd>PAGE_UP</kbd> | Go back 240 years |
| <kbd>PAGE_DOWN</kbd> | Go forward 24 years |
| <kbd>ALT</kbd> + <kbd>PAGE_DOWN</kbd> | Go forward 240 years |
| <kbd>ENTER</kbd> | Select current year |

### Troubleshooting

Expand Down
Loading