Skip to content

Commit ce73c70

Browse files
committed
Adding util/isNonInteractiveRole.js
1 parent 11f1bfa commit ce73c70

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/util/isNonInteractiveRole.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { getProp, getLiteralPropValue } from 'jsx-ast-utils';
2+
import DOMElements from './attributes/DOM.json';
3+
import roles from './attributes/role.json';
4+
5+
6+
const VALID_ROLES = Object.keys(roles)
7+
.filter(role => roles[role].interactive === false);
8+
/**
9+
* Returns boolean indicating whether the given element has a role
10+
* that is associated with a non-interactive component. Non-interactive roles
11+
* include `listitem`, `article`, or `dialog`. These are roles that indicate
12+
* for the most part containers.
13+
*
14+
* Elements with these roles should not respond or handle user interactions.
15+
* For example, an `onClick` handler should not be assigned to an element with
16+
* the role `listitem`. An element inside the `listitem`, like a button or a
17+
* link, should handle the click.
18+
*
19+
* This utility returns true for elements that are assigned a non-interactive
20+
* role. It will return false for elements that do not have a role. So whereas
21+
* a `div` might be considered non-interactive, for the purpose of this utility,
22+
* it is considered neither interactive nor non-interactive -- a determination
23+
* cannot be made in this case and false is returned.
24+
*/
25+
const isNonInteractiveRole = (tagName, attributes) => {
26+
// Do not test higher level JSX components, as we do not know what
27+
// low-level DOM element this maps to.
28+
if (Object.keys(DOMElements).indexOf(tagName) === -1) {
29+
return false;
30+
}
31+
32+
const value = getLiteralPropValue(getProp(attributes, 'role'));
33+
34+
// If value is undefined, then the role attribute will be dropped in the DOM.
35+
// If value is null, then getLiteralAttributeValue is telling us that the
36+
// value isn't in the form of a literal
37+
if (value === undefined || value === null) {
38+
return false;
39+
}
40+
41+
const normalizedValues = String(value).toUpperCase().split(' ');
42+
const isNonInteractive = normalizedValues.every(
43+
val => VALID_ROLES.indexOf(val) > -1,
44+
);
45+
46+
return isNonInteractive;
47+
};
48+
49+
export default isNonInteractiveRole;

0 commit comments

Comments
 (0)