Skip to content

Commit 390143b

Browse files
committed
Responding to evcohen and mcking65 comments
1 parent dd8d9a4 commit 390143b

File tree

4 files changed

+71
-5
lines changed

4 files changed

+71
-5
lines changed

__tests__/src/rules/onclick-has-focus-test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ ruleTester.run('onclick-has-focus', rule, {
133133
errors: [expectedError],
134134
parserOptions,
135135
},
136+
{
137+
code: '<div role="gridcell" onClick={() => void 0} />',
138+
errors: [expectedError],
139+
parserOptions,
140+
},
136141
{
137142
code: '<div role="menuitem" onClick={() => void 0} />',
138143
errors: [expectedError],
@@ -158,6 +163,16 @@ ruleTester.run('onclick-has-focus', rule, {
158163
errors: [expectedError],
159164
parserOptions,
160165
},
166+
{
167+
code: '<div role="searchbox" onClick={() => void 0} />',
168+
errors: [expectedError],
169+
parserOptions,
170+
},
171+
{
172+
code: '<div role="slider" onClick={() => void 0} />',
173+
errors: [expectedError],
174+
parserOptions,
175+
},
161176
{
162177
code: '<div role="spinbutton" onClick={() => void 0} />',
163178
errors: [expectedError],
@@ -178,5 +193,10 @@ ruleTester.run('onclick-has-focus', rule, {
178193
errors: [expectedError],
179194
parserOptions,
180195
},
196+
{
197+
code: '<div role="treeitem" onClick={() => void 0} />',
198+
errors: [expectedError],
199+
parserOptions,
200+
},
181201
],
182202
});

docs/rules/onclick-has-focus.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ Elements that are inherently focusable are as follows:
1010

1111
This rule will only test low-level DOM components, as we can not deterministically map wrapper JSX components to their correct DOM element.
1212

13+
## `tabIndex` of an element with role `gridcell`
14+
15+
Within a grid, a grid cell may itself be tabbable if it contains text content.
16+
In this case, apply a `tabIndex` of 0.
17+
18+
If the content of the grid cell is tabbable -- for example a button or link --,
19+
this apply a `tabIndex` of -1.
20+
1321
#### References
1422
1. [AX_FOCUS_02](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_02)
1523
2. [MDN](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)

src/util/attributes/role.json

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,7 @@
14741474
"GRIDCELL": {
14751475
"requiredProps": [],
14761476
"abstract": false,
1477-
"interactive": false,
1477+
"interactive": true,
14781478
"props": [
14791479
"ARIA-READONLY",
14801480
"ARIA-REQUIRED",
@@ -2303,6 +2303,40 @@
23032303
"ARIA-RELEVANT"
23042304
]
23052305
},
2306+
"SEARCHBOX": {
2307+
"props": [
2308+
"ARIA-ACTIVEDESCENDANT",
2309+
"ARIA-ATOMIC",
2310+
"ARIA-AUTOCOMPLETE",
2311+
"ARIA-BUSY",
2312+
"ARIA-CONTROLS",
2313+
"ARIA-CURRENT",
2314+
"ARIA-DESCRIBEDBY",
2315+
"ARIA-DETAILS",
2316+
"ARIA-DISABLED",
2317+
"ARIA-DROPEFFECT",
2318+
"ARIA-ERRORMESSAGE",
2319+
"ARIA-FLOWTO",
2320+
"ARIA-GRABBED",
2321+
"ARIA-HASPOPUP",
2322+
"ARIA-HIDDEN",
2323+
"ARIA-INVALID",
2324+
"ARIA-KEYSHORTCUTS",
2325+
"ARIA-LABEL",
2326+
"ARIA-LABELLEDBY",
2327+
"ARIA-LIVE",
2328+
"ARIA-MULTILINE",
2329+
"ARIA-OWNS",
2330+
"ARIA-PLACEHOLDER",
2331+
"ARIA-READONLY",
2332+
"ARIA-RELEVANT",
2333+
"ARIA-REQUIRED",
2334+
"ARIA-ROLEDESCRIPTION"
2335+
],
2336+
"requiredProps": [],
2337+
"abstract": false,
2338+
"interactive": true
2339+
},
23062340
"SECTION": {
23072341
"props": [
23082342
"ARIA-EXPANDED",
@@ -2442,7 +2476,7 @@
24422476
"ARIA-VALUENOW"
24432477
],
24442478
"abstract": false,
2445-
"interactive": false,
2479+
"interactive": true,
24462480
"props": [
24472481
"ARIA-VALUEMAX",
24482482
"ARIA-VALUEMIN",
@@ -2808,7 +2842,7 @@
28082842
"TREEITEM": {
28092843
"requiredProps": [],
28102844
"abstract": false,
2811-
"interactive": false,
2845+
"interactive": true,
28122846
"props": [
28132847
"ARIA-LEVEL",
28142848
"ARIA-POSINSET",

src/util/isInteractiveRole.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { getProp, getLiteralPropValue } from 'jsx-ast-utils';
22
import DOMElements from './attributes/DOM.json';
33
import roles from './attributes/role.json';
44

5+
6+
const VALID_ROLES = Object.keys(roles)
7+
.filter(role => roles[role].interactive === true);
58
/**
69
* Returns boolean indicating whether the given element has a role
710
* that is associated with an interactive component. Used when an element
@@ -30,8 +33,9 @@ const isInteractiveRole = (tagName, attributes) => {
3033
}
3134

3235
const normalizedValues = String(value).toUpperCase().split(' ');
33-
const validRoles = Object.keys(roles).filter(role => roles[role].interactive === true);
34-
const isInteractive = normalizedValues.every(val => validRoles.indexOf(val) > -1);
36+
const isInteractive = normalizedValues.every(
37+
val => VALID_ROLES.indexOf(val) > -1,
38+
);
3539

3640
return isInteractive;
3741
};

0 commit comments

Comments
 (0)