fix(menu): allow alternate roles to be set on menu item (#14165)

Based on the a11y guidelines, the menu items can have the `menuitemradio` and `menuitemcheckbox` roles, instead of `menuitem`. These changes allow for the consumer to set an alternate role.

Fixes #14163.
This commit is contained in:
Kristiyan Kostadinov
2018-11-27 16:33:00 +01:00
committed by Jeremy Elbourn
parent f00c8a82d0
commit 18ef94f342
2 changed files with 44 additions and 1 deletions
+5 -1
View File
@@ -15,6 +15,7 @@ import {
ViewEncapsulation,
Inject,
Optional,
Input,
} from '@angular/core';
import {
CanDisable, CanDisableCtor,
@@ -42,7 +43,7 @@ export const _MatMenuItemMixinBase: CanDisableRippleCtor & CanDisableCtor & type
exportAs: 'matMenuItem',
inputs: ['disabled', 'disableRipple'],
host: {
'role': 'menuitem',
'[attr.role]': 'role',
'class': 'mat-menu-item',
'[class.mat-menu-item-highlighted]': '_highlighted',
'[class.mat-menu-item-submenu-trigger]': '_triggersSubmenu',
@@ -59,6 +60,9 @@ export const _MatMenuItemMixinBase: CanDisableRippleCtor & CanDisableCtor & type
export class MatMenuItem extends _MatMenuItemMixinBase
implements FocusableOption, CanDisable, CanDisableRipple, OnDestroy {
/** ARIA role for the menu item. */
@Input() role: 'menuitem' | 'menuitemradio' | 'menuitemcheckbox' = 'menuitem';
private _document: Document;
/** Stream that emits when the menu item is hovered. */
+39
View File
@@ -385,6 +385,30 @@ describe('MatMenu', () => {
expect(role).toBe('menu', 'Expected panel to have the "menu" role.');
});
it('should set the "menuitem" role on the items by default', () => {
const fixture = createComponent(SimpleMenu, [], [FakeIcon]);
fixture.detectChanges();
fixture.componentInstance.trigger.openMenu();
fixture.detectChanges();
const items = Array.from(overlayContainerElement.querySelectorAll('.mat-menu-item'));
expect(items.length).toBeGreaterThan(0);
expect(items.every(item => item.getAttribute('role') === 'menuitem')).toBe(true);
});
it('should be able to set an alternate role on the menu items', () => {
const fixture = createComponent(MenuWithCheckboxItems);
fixture.detectChanges();
fixture.componentInstance.trigger.openMenu();
fixture.detectChanges();
const items = Array.from(overlayContainerElement.querySelectorAll('.mat-menu-item'));
expect(items.length).toBeGreaterThan(0);
expect(items.every(item => item.getAttribute('role') === 'menuitemcheckbox')).toBe(true);
});
it('should not throw an error on destroy', () => {
const fixture = createComponent(SimpleMenu, [], [FakeIcon]);
expect(fixture.destroy.bind(fixture)).not.toThrow();
@@ -2100,3 +2124,18 @@ class DynamicPanelMenu {
@ViewChild('one') firstMenu: MatMenu;
@ViewChild('two') secondMenu: MatMenu;
}
@Component({
template: `
<button [matMenuTriggerFor]="menu">Toggle menu</button>
<mat-menu #menu="matMenu">
<button mat-menu-item role="menuitemcheckbox" aria-checked="true">Checked</button>
<button mat-menu-item role="menuitemcheckbox" aria-checked="false">Not checked</button>
</mat-menu>
`
})
class MenuWithCheckboxItems {
@ViewChild(MatMenuTrigger) trigger: MatMenuTrigger;
}