[change] Remove special treatment of accessibilityRole="menuitem"

This role is not meant to be in the tab flow unless the element type demands
it. Users will now have to manage `onClick` and `onKeyDown` callbacks to apply
the desired interaction behavior.

Fix #1968
This commit is contained in:
Nicolas Gallagher
2021-04-22 12:47:10 -07:00
parent 22f3d142c6
commit 7775b3ab19
6 changed files with 4 additions and 42 deletions
@@ -84,7 +84,7 @@ Equivalent to [HTMLElement.readonly](https://developer.mozilla.org/en-US/docs/We
{% endcall %} {% endcall %}
{% call macro.prop('keyboardType', '?string') %} {% call macro.prop('keyboardType', '?string') %}
Hints at the type of data that might be entered by the user while editing the element or its contents. Equivalent to [HTMLElement.inputMode](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode). Safari iOS requires an ancestral <form action> element to display the search keyboard. (Not available when multiline is true.) Hints at the type of data that might be entered by the user while editing the element or its contents. Equivalent to [HTMLElement.inputMode](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode). Safari iOS requires an ancestral `<form action>` element to display the search keyboard. (Not available when multiline is true.)
{% endcall %} {% endcall %}
{% call macro.prop('lang', '?string') %} {% call macro.prop('lang', '?string') %}
@@ -1,19 +0,0 @@
/**
* Copyright (c) Nicolas Gallagher.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
const buttonLikeRoles: { [string]: boolean } = {
// ARIA button behaves like native 'button' element
button: true,
// ARIA menuitem responds to Enter/Space like a button. Spec requires AT to
// ignore ARIA roles of any children.
// https://www.w3.org/WAI/GL/wiki/Using_ARIA_menus
menuitem: true
};
export default buttonLikeRoles;
@@ -7,13 +7,11 @@
* @flow * @flow
*/ */
import buttonLikeRoles from './buttonLikeRoles';
import isDisabled from './isDisabled'; import isDisabled from './isDisabled';
import propsToAccessibilityComponent from './propsToAccessibilityComponent'; import propsToAccessibilityComponent from './propsToAccessibilityComponent';
import propsToAriaRole from './propsToAriaRole'; import propsToAriaRole from './propsToAriaRole';
const AccessibilityUtil = { const AccessibilityUtil = {
buttonLikeRoles,
isDisabled, isDisabled,
propsToAccessibilityComponent, propsToAccessibilityComponent,
propsToAriaRole propsToAriaRole
@@ -80,10 +80,6 @@ describe('modules/createDOMProps', () => {
testFocusableRole('button'); testFocusableRole('button');
}); });
describe('"accessibilityRole" of "menuitem"', () => {
testFocusableRole('menuitem');
});
describe('with unfocusable accessibilityRole', () => { describe('with unfocusable accessibilityRole', () => {
test('when "focusable" is true', () => { test('when "focusable" is true', () => {
expect(createProps({ focusable: true })).toEqual( expect(createProps({ focusable: true })).toEqual(
@@ -116,7 +112,6 @@ describe('modules/createDOMProps', () => {
expect(callsOnClick('div', 'link')).toBe(true); expect(callsOnClick('div', 'link')).toBe(true);
expect(callsOnClick('div', 'button')).toBe(true); expect(callsOnClick('div', 'button')).toBe(true);
expect(callsOnClick('div', 'textbox')).toBe(true); expect(callsOnClick('div', 'textbox')).toBe(true);
expect(callsOnClick('div', 'menuitem')).toBe(true);
expect(callsOnClick('div', 'bogus')).toBe(true); expect(callsOnClick('div', 'bogus')).toBe(true);
expect(callsOnClick('a')).toBe(true); expect(callsOnClick('a')).toBe(true);
expect(callsOnClick('button')).toBe(true); expect(callsOnClick('button')).toBe(true);
@@ -129,7 +124,6 @@ describe('modules/createDOMProps', () => {
test('is not called when disabled is true', () => { test('is not called when disabled is true', () => {
expect(callsOnClick('div', 'link', true)).toBe(false); expect(callsOnClick('div', 'link', true)).toBe(false);
expect(callsOnClick('div', 'button', true)).toBe(false); expect(callsOnClick('div', 'button', true)).toBe(false);
expect(callsOnClick('div', 'menuitem', true)).toBe(false);
expect(callsOnClick('a', undefined, true)).toBe(false); expect(callsOnClick('a', undefined, true)).toBe(false);
expect(callsOnClick('button', undefined, true)).toBe(false); expect(callsOnClick('button', undefined, true)).toBe(false);
expect(callsOnClick('input', undefined, true)).toBe(false); expect(callsOnClick('input', undefined, true)).toBe(false);
@@ -166,7 +160,6 @@ describe('modules/createDOMProps', () => {
expect(respondsToEnter('div', 'link', true)).toBe(false); expect(respondsToEnter('div', 'link', true)).toBe(false);
expect(respondsToEnter('div', 'button', true)).toBe(false); expect(respondsToEnter('div', 'button', true)).toBe(false);
expect(respondsToEnter('div', 'textbox', true)).toBe(false); expect(respondsToEnter('div', 'textbox', true)).toBe(false);
expect(respondsToEnter('div', 'menuitem', true)).toBe(false);
expect(respondsToEnter('div', 'bogus', true)).toBe(false); expect(respondsToEnter('div', 'bogus', true)).toBe(false);
}); });
@@ -190,7 +183,6 @@ describe('modules/createDOMProps', () => {
test('emulates "onClick" for "Enter" for certain roles', () => { test('emulates "onClick" for "Enter" for certain roles', () => {
expect(respondsToEnter('div', 'button')).toBe(true); expect(respondsToEnter('div', 'button')).toBe(true);
expect(respondsToEnter('div', 'menuitem')).toBe(true);
expect(respondsToEnter('div', 'textbox')).toBe(false); expect(respondsToEnter('div', 'textbox')).toBe(false);
expect(respondsToEnter('div', 'bogus')).toBe(false); expect(respondsToEnter('div', 'bogus')).toBe(false);
}); });
@@ -209,7 +201,6 @@ describe('modules/createDOMProps', () => {
test('emulates "onClick" for "Space" for certain roles', () => { test('emulates "onClick" for "Space" for certain roles', () => {
expect(respondsToSpace('div', 'button')).toBe(true); expect(respondsToSpace('div', 'button')).toBe(true);
expect(respondsToSpace('div', 'menuitem')).toBe(true);
expect(respondsToSpace('div', 'textbox')).toBe(false); expect(respondsToSpace('div', 'textbox')).toBe(false);
expect(respondsToSpace('div', 'bogus')).toBe(false); expect(respondsToSpace('div', 'bogus')).toBe(false);
}); });
@@ -365,7 +365,6 @@ const createDOMProps = (elementType, props) => {
role === 'button' || role === 'button' ||
role === 'checkbox' || role === 'checkbox' ||
role === 'link' || role === 'link' ||
role === 'menuitem' ||
role === 'radio' || role === 'radio' ||
role === 'textbox' || role === 'textbox' ||
role === 'switch' role === 'switch'
@@ -421,12 +420,7 @@ const createDOMProps = (elementType, props) => {
// Keyboard accessibility // Keyboard accessibility
// Button-like roles should trigger 'onClick' if SPACE key is pressed. // Button-like roles should trigger 'onClick' if SPACE key is pressed.
// Button-like roles should not trigger 'onClick' if they are disabled. // Button-like roles should not trigger 'onClick' if they are disabled.
if ( if (isNativeInteractiveElement || role === 'button' || (_focusable === true && !disabled)) {
isNativeInteractiveElement ||
role === 'button' ||
role === 'menuitem' ||
(_focusable === true && !disabled)
) {
const onClick = domProps.onClick; const onClick = domProps.onClick;
if (onClick != null) { if (onClick != null) {
if (disabled) { if (disabled) {
@@ -441,7 +435,7 @@ const createDOMProps = (elementType, props) => {
domProps.onKeyDown = function (e) { domProps.onKeyDown = function (e) {
const { key, repeat } = e; const { key, repeat } = e;
const isSpacebarKey = key === ' ' || key === 'Spacebar'; const isSpacebarKey = key === ' ' || key === 'Spacebar';
const isButtonRole = role === 'button' || role === 'menuitem'; const isButtonRole = role === 'button';
if (onKeyDown != null) { if (onKeyDown != null) {
onKeyDown(e); onKeyDown(e);
} }
@@ -134,9 +134,7 @@ const isValidKeyPress = (event) => {
const target = event.currentTarget; const target = event.currentTarget;
const role = target.getAttribute('role'); const role = target.getAttribute('role');
const isSpacebar = key === ' ' || key === 'Spacebar'; const isSpacebar = key === ' ' || key === 'Spacebar';
return ( return !event.repeat && (key === 'Enter' || (isSpacebar && role === 'button'));
!event.repeat && (key === 'Enter' || (isSpacebar && (role === 'button' || role === 'menuitem')))
);
}; };
const DEFAULT_LONG_PRESS_DELAY_MS = 450; // 500 - 50 const DEFAULT_LONG_PRESS_DELAY_MS = 450; // 500 - 50