mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-27 16:22:20 +00:00
[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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user