@arcaauth/eslint-plugin-jsx-a11y 6.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/.babelrc +17 -0
  2. package/.eslintrc +44 -0
  3. package/CHANGELOG.md +774 -0
  4. package/LICENSE.md +8 -0
  5. package/README.md +423 -0
  6. package/__mocks__/IdentifierMock.js +15 -0
  7. package/__mocks__/JSXAttributeMock.js +39 -0
  8. package/__mocks__/JSXElementMock.js +37 -0
  9. package/__mocks__/JSXExpressionContainerMock.js +15 -0
  10. package/__mocks__/JSXSpreadAttributeMock.js +18 -0
  11. package/__mocks__/JSXTextMock.js +17 -0
  12. package/__mocks__/LiteralMock.js +17 -0
  13. package/__mocks__/genInteractives.js +218 -0
  14. package/__tests__/__util__/axeMapping.js +6 -0
  15. package/__tests__/__util__/helpers/getESLintCoreRule.js +9 -0
  16. package/__tests__/__util__/helpers/parsers.js +186 -0
  17. package/__tests__/__util__/parserOptionsMapper.js +53 -0
  18. package/__tests__/__util__/ruleOptionsMapperFactory.js +33 -0
  19. package/__tests__/index-test.js +40 -0
  20. package/__tests__/src/rules/accessible-emoji-test.js +66 -0
  21. package/__tests__/src/rules/alt-text-test.js +291 -0
  22. package/__tests__/src/rules/anchor-ambiguous-text-test.js +117 -0
  23. package/__tests__/src/rules/anchor-has-content-test.js +54 -0
  24. package/__tests__/src/rules/anchor-is-valid-test.js +532 -0
  25. package/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js +95 -0
  26. package/__tests__/src/rules/aria-props-test.js +69 -0
  27. package/__tests__/src/rules/aria-proptypes-test.js +311 -0
  28. package/__tests__/src/rules/aria-role-test.js +118 -0
  29. package/__tests__/src/rules/aria-unsupported-elements-test.js +75 -0
  30. package/__tests__/src/rules/autocomplete-valid-test.js +77 -0
  31. package/__tests__/src/rules/click-events-have-key-events-test.js +77 -0
  32. package/__tests__/src/rules/control-has-associated-label-test.js +327 -0
  33. package/__tests__/src/rules/heading-has-content-test.js +85 -0
  34. package/__tests__/src/rules/html-has-lang-test.js +42 -0
  35. package/__tests__/src/rules/iframe-has-title-test.js +55 -0
  36. package/__tests__/src/rules/img-redundant-alt-test.js +137 -0
  37. package/__tests__/src/rules/interactive-supports-focus-test.js +267 -0
  38. package/__tests__/src/rules/label-has-associated-control-test.js +243 -0
  39. package/__tests__/src/rules/label-has-for-test.js +235 -0
  40. package/__tests__/src/rules/lang-test.js +59 -0
  41. package/__tests__/src/rules/media-has-caption-test.js +220 -0
  42. package/__tests__/src/rules/mouse-events-have-key-events-test.js +154 -0
  43. package/__tests__/src/rules/no-access-key-test.js +48 -0
  44. package/__tests__/src/rules/no-aria-hidden-on-focusable-test.js +44 -0
  45. package/__tests__/src/rules/no-autofocus-test.js +68 -0
  46. package/__tests__/src/rules/no-distracting-elements-test.js +51 -0
  47. package/__tests__/src/rules/no-interactive-element-to-noninteractive-role-test.js +405 -0
  48. package/__tests__/src/rules/no-noninteractive-element-interactions-test.js +502 -0
  49. package/__tests__/src/rules/no-noninteractive-element-to-interactive-role-test.js +500 -0
  50. package/__tests__/src/rules/no-noninteractive-tabindex-test.js +123 -0
  51. package/__tests__/src/rules/no-onchange-test.js +57 -0
  52. package/__tests__/src/rules/no-redundant-roles-test.js +98 -0
  53. package/__tests__/src/rules/no-static-element-interactions-test.js +501 -0
  54. package/__tests__/src/rules/prefer-tag-over-role-test.js +63 -0
  55. package/__tests__/src/rules/role-has-required-aria-props-test.js +134 -0
  56. package/__tests__/src/rules/role-supports-aria-props-test.js +570 -0
  57. package/__tests__/src/rules/scope-test.js +50 -0
  58. package/__tests__/src/rules/tabindex-no-positive-test.js +55 -0
  59. package/__tests__/src/util/attributesComparator-test.js +91 -0
  60. package/__tests__/src/util/getAccessibleChildText-test.js +174 -0
  61. package/__tests__/src/util/getComputedRole-test.js +71 -0
  62. package/__tests__/src/util/getElementType-test.js +154 -0
  63. package/__tests__/src/util/getExplicitRole-test.js +35 -0
  64. package/__tests__/src/util/getImplicitRole-test.js +25 -0
  65. package/__tests__/src/util/getSuggestion-test.js +33 -0
  66. package/__tests__/src/util/getTabIndex-test.js +85 -0
  67. package/__tests__/src/util/hasAccessibleChild-test.js +157 -0
  68. package/__tests__/src/util/implicitRoles/input-test.js +87 -0
  69. package/__tests__/src/util/implicitRoles/menu-test.js +20 -0
  70. package/__tests__/src/util/implicitRoles/menuitem-test.js +38 -0
  71. package/__tests__/src/util/isAbstractRole-test.js +51 -0
  72. package/__tests__/src/util/isContentEditable-test.js +52 -0
  73. package/__tests__/src/util/isDOMElement-test.js +30 -0
  74. package/__tests__/src/util/isDisabledElement-test.js +88 -0
  75. package/__tests__/src/util/isFocusable-test.js +111 -0
  76. package/__tests__/src/util/isInteractiveElement-test.js +104 -0
  77. package/__tests__/src/util/isInteractiveRole-test.js +59 -0
  78. package/__tests__/src/util/isNonInteractiveElement-test.js +97 -0
  79. package/__tests__/src/util/isNonInteractiveRole-test.js +59 -0
  80. package/__tests__/src/util/isNonLiteralProperty-test.js +52 -0
  81. package/__tests__/src/util/isSemanticRoleElement-test.js +72 -0
  82. package/__tests__/src/util/mayContainChildComponent-test.js +219 -0
  83. package/__tests__/src/util/mayHaveAccessibleLabel-test.js +256 -0
  84. package/__tests__/src/util/parserOptionsMapper-test.js +93 -0
  85. package/__tests__/src/util/schemas-test.js +35 -0
  86. package/docs/rules/accessible-emoji.md +30 -0
  87. package/docs/rules/alt-text.md +168 -0
  88. package/docs/rules/anchor-ambiguous-text.md +91 -0
  89. package/docs/rules/anchor-has-content.md +64 -0
  90. package/docs/rules/anchor-is-valid.md +270 -0
  91. package/docs/rules/aria-activedescendant-has-tabindex.md +52 -0
  92. package/docs/rules/aria-props.md +29 -0
  93. package/docs/rules/aria-proptypes.md +30 -0
  94. package/docs/rules/aria-role.md +51 -0
  95. package/docs/rules/aria-unsupported-elements.md +30 -0
  96. package/docs/rules/autocomplete-valid.md +49 -0
  97. package/docs/rules/click-events-have-key-events.md +28 -0
  98. package/docs/rules/control-has-associated-label.md +113 -0
  99. package/docs/rules/heading-has-content.md +67 -0
  100. package/docs/rules/html-has-lang.md +31 -0
  101. package/docs/rules/iframe-has-title.md +37 -0
  102. package/docs/rules/img-redundant-alt.md +48 -0
  103. package/docs/rules/interactive-supports-focus.md +156 -0
  104. package/docs/rules/label-has-associated-control.md +152 -0
  105. package/docs/rules/label-has-for.md +130 -0
  106. package/docs/rules/lang.md +31 -0
  107. package/docs/rules/media-has-caption.md +48 -0
  108. package/docs/rules/mouse-events-have-key-events.md +58 -0
  109. package/docs/rules/no-access-key.md +30 -0
  110. package/docs/rules/no-aria-hidden-on-focusable.md +37 -0
  111. package/docs/rules/no-autofocus.md +43 -0
  112. package/docs/rules/no-distracting-elements.md +41 -0
  113. package/docs/rules/no-interactive-element-to-noninteractive-role.md +73 -0
  114. package/docs/rules/no-noninteractive-element-interactions.md +145 -0
  115. package/docs/rules/no-noninteractive-element-to-interactive-role.md +76 -0
  116. package/docs/rules/no-noninteractive-tabindex.md +115 -0
  117. package/docs/rules/no-onchange.md +36 -0
  118. package/docs/rules/no-redundant-roles.md +46 -0
  119. package/docs/rules/no-static-element-interactions.md +114 -0
  120. package/docs/rules/prefer-tag-over-role.md +32 -0
  121. package/docs/rules/role-has-required-aria-props.md +31 -0
  122. package/docs/rules/role-supports-aria-props.md +39 -0
  123. package/docs/rules/scope.md +30 -0
  124. package/docs/rules/tabindex-no-positive.md +32 -0
  125. package/lib/configs/flat-config-base.js +11 -0
  126. package/lib/configs/legacy-config-base.js +9 -0
  127. package/lib/index.js +209 -0
  128. package/lib/rules/accessible-emoji.js +63 -0
  129. package/lib/rules/alt-text.js +218 -0
  130. package/lib/rules/anchor-ambiguous-text.js +64 -0
  131. package/lib/rules/anchor-has-content.js +60 -0
  132. package/lib/rules/anchor-is-valid.js +122 -0
  133. package/lib/rules/aria-activedescendant-has-tabindex.js +66 -0
  134. package/lib/rules/aria-props.js +59 -0
  135. package/lib/rules/aria-proptypes.js +114 -0
  136. package/lib/rules/aria-role.js +89 -0
  137. package/lib/rules/aria-unsupported-elements.js +64 -0
  138. package/lib/rules/autocomplete-valid.js +67 -0
  139. package/lib/rules/click-events-have-key-events.js +68 -0
  140. package/lib/rules/control-has-associated-label.js +103 -0
  141. package/lib/rules/heading-has-content.js +61 -0
  142. package/lib/rules/html-has-lang.js +50 -0
  143. package/lib/rules/iframe-has-title.js +50 -0
  144. package/lib/rules/img-redundant-alt.js +88 -0
  145. package/lib/rules/interactive-supports-focus.js +87 -0
  146. package/lib/rules/label-has-associated-control.js +127 -0
  147. package/lib/rules/label-has-for.js +150 -0
  148. package/lib/rules/lang.js +68 -0
  149. package/lib/rules/media-has-caption.js +96 -0
  150. package/lib/rules/mouse-events-have-key-events.js +94 -0
  151. package/lib/rules/no-access-key.js +43 -0
  152. package/lib/rules/no-aria-hidden-on-focusable.js +47 -0
  153. package/lib/rules/no-autofocus.js +62 -0
  154. package/lib/rules/no-distracting-elements.js +54 -0
  155. package/lib/rules/no-interactive-element-to-noninteractive-role.js +81 -0
  156. package/lib/rules/no-noninteractive-element-interactions.js +95 -0
  157. package/lib/rules/no-noninteractive-element-to-interactive-role.js +80 -0
  158. package/lib/rules/no-noninteractive-tabindex.js +109 -0
  159. package/lib/rules/no-onchange.js +52 -0
  160. package/lib/rules/no-redundant-roles.js +86 -0
  161. package/lib/rules/no-static-element-interactions.js +102 -0
  162. package/lib/rules/prefer-tag-over-role.js +75 -0
  163. package/lib/rules/role-has-required-aria-props.js +88 -0
  164. package/lib/rules/role-supports-aria-props.js +78 -0
  165. package/lib/rules/scope.js +58 -0
  166. package/lib/rules/tabindex-no-positive.js +53 -0
  167. package/lib/util/attributesComparator.js +34 -0
  168. package/lib/util/getAccessibleChildText.js +55 -0
  169. package/lib/util/getComputedRole.js +19 -0
  170. package/lib/util/getElementType.js +30 -0
  171. package/lib/util/getExplicitRole.js +27 -0
  172. package/lib/util/getImplicitRole.js +24 -0
  173. package/lib/util/getSuggestion.js +32 -0
  174. package/lib/util/getTabIndex.js +34 -0
  175. package/lib/util/hasAccessibleChild.js +30 -0
  176. package/lib/util/implicitRoles/a.js +17 -0
  177. package/lib/util/implicitRoles/area.js +17 -0
  178. package/lib/util/implicitRoles/article.js +13 -0
  179. package/lib/util/implicitRoles/aside.js +13 -0
  180. package/lib/util/implicitRoles/body.js +13 -0
  181. package/lib/util/implicitRoles/button.js +13 -0
  182. package/lib/util/implicitRoles/datalist.js +13 -0
  183. package/lib/util/implicitRoles/details.js +13 -0
  184. package/lib/util/implicitRoles/dialog.js +13 -0
  185. package/lib/util/implicitRoles/form.js +13 -0
  186. package/lib/util/implicitRoles/h1.js +13 -0
  187. package/lib/util/implicitRoles/h2.js +13 -0
  188. package/lib/util/implicitRoles/h3.js +13 -0
  189. package/lib/util/implicitRoles/h4.js +13 -0
  190. package/lib/util/implicitRoles/h5.js +13 -0
  191. package/lib/util/implicitRoles/h6.js +13 -0
  192. package/lib/util/implicitRoles/hr.js +13 -0
  193. package/lib/util/implicitRoles/img.js +31 -0
  194. package/lib/util/implicitRoles/index.js +82 -0
  195. package/lib/util/implicitRoles/input.js +38 -0
  196. package/lib/util/implicitRoles/li.js +13 -0
  197. package/lib/util/implicitRoles/link.js +17 -0
  198. package/lib/util/implicitRoles/menu.js +19 -0
  199. package/lib/util/implicitRoles/menuitem.js +28 -0
  200. package/lib/util/implicitRoles/meter.js +13 -0
  201. package/lib/util/implicitRoles/nav.js +13 -0
  202. package/lib/util/implicitRoles/ol.js +13 -0
  203. package/lib/util/implicitRoles/option.js +13 -0
  204. package/lib/util/implicitRoles/output.js +13 -0
  205. package/lib/util/implicitRoles/progress.js +13 -0
  206. package/lib/util/implicitRoles/section.js +13 -0
  207. package/lib/util/implicitRoles/select.js +13 -0
  208. package/lib/util/implicitRoles/tbody.js +13 -0
  209. package/lib/util/implicitRoles/textarea.js +13 -0
  210. package/lib/util/implicitRoles/tfoot.js +13 -0
  211. package/lib/util/implicitRoles/thead.js +13 -0
  212. package/lib/util/implicitRoles/ul.js +13 -0
  213. package/lib/util/isAbstractRole.js +23 -0
  214. package/lib/util/isContentEditable.js +13 -0
  215. package/lib/util/isDOMElement.js +15 -0
  216. package/lib/util/isDisabledElement.js +23 -0
  217. package/lib/util/isFocusable.js +23 -0
  218. package/lib/util/isHiddenFromScreenReader.js +26 -0
  219. package/lib/util/isInteractiveElement.js +116 -0
  220. package/lib/util/isInteractiveRole.js +54 -0
  221. package/lib/util/isNonInteractiveElement.js +131 -0
  222. package/lib/util/isNonInteractiveRole.js +55 -0
  223. package/lib/util/isNonLiteralProperty.js +29 -0
  224. package/lib/util/isPresentationRole.js +13 -0
  225. package/lib/util/isSemanticRoleElement.js +54 -0
  226. package/lib/util/mayContainChildComponent.js +50 -0
  227. package/lib/util/mayHaveAccessibleLabel.js +95 -0
  228. package/lib/util/schemas.js +52 -0
  229. package/package.json +120 -0
@@ -0,0 +1,145 @@
1
+ # jsx-a11y/no-noninteractive-element-interactions
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Non-interactive HTML elements and non-interactive ARIA roles indicate _content_ and _containers_ in the user interface. A non-interactive element does not support event handlers (mouse and key handlers). Non-interactive elements include `<main>`, `<area>`, `<h1>` (,`<h2>`, etc), `<p>`, `<img>`, `<li>`, `<ul>` and `<ol>`. Non-interactive [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
8
+
9
+ ## How do I resolve this error?
10
+
11
+ ### Case: This element acts like a button, link, menuitem, etc
12
+
13
+ Move the event handler function to an inner element that is either a semantically interactive element (`<button>`, `<a href>`) or that has an interactive role. This leaves the _content_ or _container_ semantic value of this element intact.
14
+
15
+ Common interactive roles include:
16
+
17
+ 1. `button`
18
+ 1. `link`
19
+ 1. `checkbox`
20
+ 1. `menuitem`
21
+ 1. `menuitemcheckbox`
22
+ 1. `menuitemradio`
23
+ 1. `option`
24
+ 1. `radio`
25
+ 1. `searchbox`
26
+ 1. `switch`
27
+ 1. `textbox`
28
+
29
+ Note: Adding a role to your element does **not** add behavior. When a semantic HTML element like `<button>` is used, then it will also respond to Enter key presses when it has focus. The developer is responsible for providing the expected behavior of an element that the role suggests it would have: focusability and key press support.
30
+ see [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex).
31
+
32
+ ### Case: This element is catching bubbled events from elements that it contains
33
+
34
+ Move the event handler function to an inner element like `<div>` and give that element a role of `presentation`. This leaves the _content_ or _container_ semantic value of this element intact.
35
+
36
+ ```jsx
37
+ <div role="article">
38
+ <div
39
+ onClick="onClickHandler"
40
+ onKeyPress={onKeyPressHandler}
41
+ role="presentation">
42
+ {this.props.children}
43
+ </div>
44
+ </div>
45
+ ```
46
+
47
+ Marking an element with the role `presentation` indicates to assistive technology that this element should be ignored; it exists to support the web application and is not meant for humans to interact with directly.
48
+
49
+ ### Case: This is a heading that expands/collapses content on the package
50
+
51
+ Headers often double as expand/collapse controls for the content they headline. An accordion component is a common example of this pattern. Rather than assign the interaction handling code to the heading itself, put a button inside the heading instead. This pattern retains the role of the heading and the role of the button.
52
+
53
+ ```jsx
54
+ <h3>
55
+ <button onClick={this._expandSection}>News</button>
56
+ </h3>
57
+ <ul id="articles-list">
58
+ <li>...</li>
59
+ </ul>
60
+ ```
61
+
62
+ ### Case: This element is a table cell
63
+
64
+ Table cells (and tables in general) are meant to contain data. ARIA provides us with a construct called a [Grid](https://w3c.github.io/aria-practices/#grid) that is essentially a 2 dimensional logical container for content and interactive elements.
65
+
66
+ You have two options in this case.
67
+
68
+ #### Option 1, move the interactive content inside the table cells
69
+
70
+ For instance, move the button inside the cell:
71
+
72
+ ```jsx
73
+ <table>
74
+ <tr>
75
+ <td><button>Sort</button></td>
76
+ </tr>
77
+ </table>
78
+ ```
79
+
80
+ This preserves the table cell semantics and the button semantics; the two are not conflated on the cell.
81
+
82
+ #### Option 2, convert the table into an ARIA grid
83
+
84
+ If your user interface has a table-like layout, but is filled with interactive components in the cells, consider converting the table into a grid.
85
+
86
+ ```jsx
87
+ <table role="grid">
88
+ <tr>
89
+ <td role="gridcell" onClick={this.sort}>Sort</td>
90
+ </tr>
91
+ </table>
92
+ ```
93
+
94
+ You can also put the interactive content inside the grid cell. This maintains the semantic distinction between the cell and the interaction content, although a grid cell can be interactive.
95
+
96
+ ## Rule options
97
+
98
+ You may configure which handler props should be taken into account when applying this rule. The recommended configuration includes the following 6 handlers.
99
+
100
+ ```javascript
101
+ 'jsx-a11y/no-noninteractive-element-interactions': [
102
+ 'error',
103
+ {
104
+ handlers: [
105
+ 'onClick',
106
+ 'onMouseDown',
107
+ 'onMouseUp',
108
+ 'onKeyPress',
109
+ 'onKeyDown',
110
+ 'onKeyUp',
111
+ ],
112
+ },
113
+ ],
114
+ ```
115
+
116
+ Adjust the list of handler prop names in the handlers array to increase or decrease the coverage surface of this rule in your codebase.
117
+
118
+ ### Succeed
119
+
120
+ ```jsx
121
+ <div onClick={() => void 0} role="button" />
122
+ <div onClick={() => void 0} role="presentation" />
123
+ <input type="text" onClick={() => void 0} /> // Interactive element does not require role.
124
+ <button onClick={() => void 0} className="foo" /> // button is interactive.
125
+ <div onClick={() => void 0} role="button" aria-hidden /> // This is hidden from screen reader.
126
+ <Input onClick={() => void 0} type="hidden" /> // This is a higher-level DOM component
127
+ ```
128
+
129
+ ### Fail
130
+
131
+ ```jsx
132
+ <li onClick={() => void 0} />
133
+ <div onClick={() => void 0} role="listitem" />
134
+ ```
135
+
136
+ ## Accessibility guidelines
137
+
138
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
139
+
140
+ ### Resources
141
+
142
+ - [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)
143
+ - [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)
144
+ - [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
145
+ - [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)
@@ -0,0 +1,76 @@
1
+ # jsx-a11y/no-noninteractive-element-to-interactive-role
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Non-interactive HTML elements indicate _content_ and _containers_ in the user interface. Non-interactive elements include `<main>`, `<area>`, `<h1>` (,`<h2>`, etc), `<img>`, `<li>`, `<ul>` and `<ol>`.
8
+
9
+ Interactive HTML elements indicate _controls_ in the user interface. Interactive elements include `<a href>`, `<button>`, `<input>`, `<select>`, `<textarea>`.
10
+
11
+ [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) should not be used to convert a non-interactive element to an interactive element. Interactive ARIA roles include `button`, `link`, `checkbox`, `menuitem`, `menuitemcheckbox`, `menuitemradio`, `option`, `radio`, `searchbox`, `switch` and `textbox`.
12
+
13
+ ## How do I resolve this error?
14
+
15
+ ### Case: This element should be a control, like a button
16
+
17
+ Put the control inside the non-interactive container element.
18
+
19
+ ```jsx
20
+ <li>
21
+ <div
22
+ role="button"
23
+ onClick={() => {}}
24
+ onKeyPress={() => {}}>
25
+ Save
26
+ </div>
27
+ </li>
28
+ ```
29
+
30
+ Or wrap the content inside your interactive element.
31
+
32
+ ```jsx
33
+ <div
34
+ role="button"
35
+ onClick={() => {}}
36
+ onKeyPress={() => {}}
37
+ tabIndex="0">
38
+ <img src="some/file.png" alt="Save" />
39
+ </div>
40
+ ```
41
+
42
+ ## Rule options
43
+
44
+ The recommended options for this rule allow several common interactive roles to be applied to a non-interactive element. The options are provided as an object keyed by HTML element name; the value is an array of interactive roles that are allowed on the specified element.
45
+
46
+ ```js
47
+ {
48
+ 'no-noninteractive-element-to-interactive-role': [
49
+ 'error',
50
+ {
51
+ ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
52
+ ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
53
+ li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
54
+ table: ['grid'],
55
+ td: ['gridcell'],
56
+ },
57
+ ]
58
+ }
59
+ ```
60
+
61
+ Under the recommended options, the following code is valid. It would be invalid under the strict rules.
62
+
63
+ ```jsx
64
+ <ul role="menu" />
65
+ ```
66
+
67
+ ## Accessibility guidelines
68
+
69
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
70
+
71
+ ### Resources
72
+
73
+ - [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)
74
+ - [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)
75
+ - [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
76
+ - [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)
@@ -0,0 +1,115 @@
1
+ # jsx-a11y/no-noninteractive-tabindex
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Tab key navigation should be limited to elements on the page that can be interacted with. Thus it is not necessary to add a tabindex to items in an unordered list, for example, to make them navigable through assistive technology. These applications already afford page traversal mechanisms based on the HTML of the page. Generally, we should try to reduce the size of the page's tab ring rather than increasing it.
8
+
9
+ ## How do I resolve this error?
10
+
11
+ ### Case: I am using an `<a>` tag. Isn't that interactive?
12
+
13
+ The `<a>` tag is tricky. Consider the following:
14
+
15
+ ```jsx
16
+ <a>Edit</a>
17
+ <a href="#">Edit</a>
18
+ <a role="button">Edit</a>
19
+ ```
20
+
21
+ The bare `<a>` tag is an _anchor_. It has no semantic AX API mapping in either ARIA or the AXObject model. It's as meaningful as `<div>`, which is to say it has no meaning. An `<a>` tag with an `href` attribute has an inherent role of `link`. An `<a>` tag with an explicit role obtains the designated role. In the example above, this role is `button`.
22
+
23
+ ### Case: I am using "semantic" HTML. Isn't that interactive?
24
+
25
+ If we take a step back into the field of linguistics for a moment, let's consider what it means for something to be "semantic". Nothing, in and of itself, has meaning. Meaning is constructed through dialogue. A speaker intends a meaning and a listener/observer interprets a meaning. Each participant constructs their own meaning through dialogue. There is no intrinsic or isolated meaning outside of interaction. Thus, we must ask, given that we have a "speaker" who communicates via "semantic" HTML, who is listening/observing?
26
+
27
+ In our case, the observer is the Accessibility (AX) API. Browsers interpret HTML (inflected at times by ARIA) to construct a meaning (AX Tree) of the page. Whatever the semantic HTML intends has only the force of suggestion to the AX API. Therefore, we have inconsistencies. For example, there is not yet an ARIA role for `text` or `label` and thus no way to change a `<label>` into plain text or a `<span>` into a label via ARIA. `<div>` has an AXObject correpondant `DivRole`, but no such object maps to `<span>`.
28
+
29
+ What this lint rule endeavors to do is apply the AX API understanding of the semantics of an HTML document back onto your code. The concept of interactivity boils down to whether a user can do something with the indicated or focused component.
30
+
31
+ Common interactive roles include:
32
+
33
+ 1. `button`
34
+ 1. `link`
35
+ 1. `checkbox`
36
+ 1. `menuitem`
37
+ 1. `menuitemcheckbox`
38
+ 1. `menuitemradio`
39
+ 1. `option`
40
+ 1. `radio`
41
+ 1. `searchbox`
42
+ 1. `switch`
43
+ 1. `textbox`
44
+
45
+ Endeavor to limit tabbable elements to those that a user can act upon.
46
+
47
+ ### Case: Shouldn't I add a tabindex so that users can navigate to this item?
48
+
49
+ It is not necessary to put a tabindex on an `<article>`, for instance or on `<li>` items; assistive technologies provide affordances to users to find and traverse these containers. Most elements that require a tabindex -- `<a href>`, `<button>`, `<input>`, `<textarea>` -- have it already.
50
+
51
+ Your application might require an exception to this rule in the case of an element that captures incoming tab traversal for a composite widget. In that case, turn off this rule on a per instance basis. This is an uncommon case.
52
+
53
+ If you know that a particular element will be scrollable, you might want to add `tabindex="0"` if your website supports browsers that don't make these containers keyboard-focusable. The current status for this platform feature can be tracked in [Chrome Platform Status "Feature: Keyboard-focusable scroll containers"](https://www.chromestatus.com/feature/5231964663578624).
54
+
55
+ ```jsx
56
+ // eslint-disable-next-line no-noninteractive-tabindex
57
+ <pre tabIndex="0">
58
+ <code>{someLongCode}</code>
59
+ </pre>
60
+ ```
61
+
62
+ ## Rule options
63
+
64
+ The recommended options for this rule allow `tabIndex` on elements with the noninteractive `tabpanel` role. Adding `tabIndex` to a tabpanel is a recommended practice in some instances.
65
+
66
+ ```javascript
67
+ 'jsx-a11y/no-noninteractive-tabindex': [
68
+ 'error',
69
+ {
70
+ tags: [],
71
+ roles: ['tabpanel'],
72
+ allowExpressionValues: true,
73
+ },
74
+ ]
75
+ ```
76
+
77
+ The `allowExpressionValues` option determines whether the `role` attribute is allowed to be assigned using an expression. For example, the following would pass in recommended mode if `allowExpressionValues` is set to be `true`:
78
+
79
+ ```jsx
80
+ <div role={ROLE_BUTTON} onClick={() => {}} tabIndex="0" />;
81
+ // In case of a conditional expression, there should be literals on both sides of ternary operator
82
+ <div role={isButton ? "button" : "link"} onClick={() => {}} tabIndex="0" />;
83
+ ```
84
+
85
+ ### Succeed
86
+
87
+ ```jsx
88
+ <div />
89
+ <MyButton tabIndex={0} />
90
+ <button />
91
+ <button tabIndex="0" />
92
+ <button tabIndex={0} />
93
+ <div />
94
+ <div tabIndex="-1" />
95
+ <div role="button" tabIndex="0" />
96
+ <div role="article" tabIndex="-1" />
97
+ <article tabIndex="-1" />
98
+ ```
99
+
100
+ ### Fail
101
+
102
+ ```jsx
103
+ <div tabIndex="0" />
104
+ <div role="article" tabIndex="0" />
105
+ <article tabIndex="0" />
106
+ <article tabIndex={0} />
107
+ ```
108
+
109
+ ## Accessibility guidelines
110
+
111
+ - [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)
112
+
113
+ ### Resources
114
+
115
+ - [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
@@ -0,0 +1,36 @@
1
+ # jsx-a11y/no-onchange
2
+
3
+ ❌ This rule is deprecated.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ ⚠️ **Deprecated:** This rule is based on reports of behavior of [old browsers (eg. IE 10 and below)](https://www.quirksmode.org/dom/events/change.html#t05). In the meantime, this behavior has been corrected, both in newer versions of browsers as well as [in the DOM spec](https://bugzilla.mozilla.org/show_bug.cgi?id=969068#c2).
8
+
9
+ Enforce usage of `onBlur` over/in parallel with `onChange` on select menu elements for accessibility. `onBlur` **should** be used instead of `onChange`, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users. `onBlur` is a more declarative action by the user: for instance in a dropdown, using the arrow keys to toggle between options will trigger the `onChange` event in some browsers. Regardless, when a change of context results from an `onBlur` event or an `onChange` event, the user should be notified of the change unless it occurs below the currently focused element.
10
+
11
+ ## Rule details
12
+
13
+ This rule takes no arguments.
14
+
15
+ ### Succeed
16
+ ```jsx
17
+ <select onBlur={updateModel}>
18
+ <option/>
19
+ </select>
20
+
21
+ <select>
22
+ <option onBlur={handleOnBlur} onChange={handleOnChange} />
23
+ </select>
24
+ ```
25
+
26
+ ### Fail
27
+ ```jsx
28
+ <select onChange={updateModel} />
29
+ ```
30
+
31
+ ## Accessibility guidelines
32
+ - [WCAG 3.2.2](https://www.w3.org/WAI/WCAG21/Understanding/on-input)
33
+
34
+ ### Resources
35
+ - [onChange Event Accessibility Issues](https://web.archive.org/web/20191207202425/http://cita.disability.uiuc.edu/html-best-practices/auto/onchange.php)
36
+ - [onChange Select Menu](https://www.themaninblue.com/writing/perspective/2004/10/19/)
@@ -0,0 +1,46 @@
1
+ # jsx-a11y/no-redundant-roles
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Some HTML elements have native semantics that are implemented by the browser. This includes default/implicit ARIA roles. Setting an ARIA role that matches its default/implicit role is redundant since it is already set by the browser.
8
+
9
+ ## Rule options
10
+
11
+ The default options for this rule allow an implicit role of `navigation` to be applied to a `nav` element as is [advised by w3](https://www.w3.org/WAI/GL/wiki/Using_HTML5_nav_element#Example:The_.3Cnav.3E_element). The options are provided as an object keyed by HTML element name; the value is an array of implicit ARIA roles that are allowed on the specified element.
12
+
13
+ ```js
14
+ {
15
+ 'jsx-a11y/no-redundant-roles': [
16
+ 'error',
17
+ {
18
+ nav: ['navigation'],
19
+ },
20
+ ],
21
+ }
22
+ ```
23
+
24
+ ### Succeed
25
+
26
+ ```jsx
27
+ <div />
28
+ <button role="presentation" />
29
+ <MyComponent role="main" />
30
+ ```
31
+
32
+ ### Fail
33
+
34
+ ```jsx
35
+ <button role="button" />
36
+ <img role="img" src="foo.jpg" />
37
+ ```
38
+
39
+ ## Accessibility guidelines
40
+
41
+ General best practice (reference resources)
42
+
43
+ ### Resources
44
+
45
+ - [ARIA Spec, ARIA Adds Nothing to Default Semantics of Most HTML Elements](https://www.w3.org/TR/using-aria/#aria-does-nothing)
46
+ - [Identifying SVG as an image](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#identifying_svg_as_an_image)
@@ -0,0 +1,114 @@
1
+ # jsx-a11y/no-static-element-interactions
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Static HTML elements do not have semantic meaning. This is clear in the case of `<div>` and `<span>`. It is less so clear in the case of elements that _seem_ semantic, but that do not have a semantic mapping in the accessibility layer. For example `<a>`, `<big>`, `<blockquote>`, `<footer>`, `<picture>`, `<strike>` and `<time>` -- to name a few -- have no semantic layer mapping. They are as void of meaning as `<div>`.
8
+
9
+ The [WAI-ARIA `role` attribute](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) confers a semantic mapping to an element. The semantic value can then be expressed to a user via assistive technology.
10
+
11
+ In order to add interactivity such as a mouse or key event listener to a static element, that element must be given a role value as well.
12
+
13
+ ## How do I resolve this error?
14
+
15
+ ### Case: This element acts like a button, link, menuitem, etc
16
+
17
+ Indicate the element's role with the `role` attribute:
18
+
19
+ ```jsx
20
+ <div
21
+ onClick={onClickHandler}
22
+ onKeyPress={onKeyPressHandler}
23
+ role="button"
24
+ tabindex="0">
25
+ Save
26
+ </div>
27
+ ```
28
+
29
+ Common interactive roles include:
30
+
31
+ 1. `button`
32
+ 1. `link`
33
+ 1. `checkbox`
34
+ 1. `menuitem`
35
+ 1. `menuitemcheckbox`
36
+ 1. `menuitemradio`
37
+ 1. `option`
38
+ 1. `radio`
39
+ 1. `searchbox`
40
+ 1. `switch`
41
+ 1. `textbox`
42
+
43
+ Note: Adding a role to your element does **not** add behavior. When a semantic HTML element like `<button>` is used, then it will also respond to Enter key presses when it has focus. The developer is responsible for providing the expected behavior of an element that the role suggests it would have: focusability and key press support.
44
+
45
+ ### Case: The event handler is only being used to capture bubbled events
46
+
47
+ If your element is catching bubbled click or key events from descendant elements, there are no appropriate roles for your element: you will have to deactivate the rule. Consider explaining the reason for disabling the rule as well.
48
+
49
+ ```jsx
50
+ {/* The <div> element has a child <button> element that allows keyboard interaction */}
51
+ {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
52
+ <div onClick={this.handleButtonClick}>
53
+ <button>Save</button>
54
+ <button>Cancel</button>
55
+ </div>
56
+ ```
57
+
58
+ Do not use the role `presentation` on the element: it removes the element's semantics, and may also remove its children's semantics, creating big issues with assistive technology.
59
+
60
+ ## Rule options
61
+
62
+ You may configure which handler props should be taken into account when applying this rule. The recommended configuration includes the following 6 handlers and the `allowExpressionValues` option.
63
+
64
+ ```javascript
65
+ 'jsx-a11y/no-static-element-interactions': [
66
+ 'error',
67
+ {
68
+ handlers: [
69
+ 'onClick',
70
+ 'onMouseDown',
71
+ 'onMouseUp',
72
+ 'onKeyPress',
73
+ 'onKeyDown',
74
+ 'onKeyUp',
75
+ ],
76
+ allowExpressionValues: true,
77
+ },
78
+ ],
79
+ ```
80
+
81
+ Adjust the list of handler prop names in the handlers array to increase or decrease the coverage surface of this rule in your codebase.
82
+
83
+ The `allowExpressionValues` option determines whether the `role` attribute is allowed to be assigned using an expression. For example, the following would pass in recommended mode if `allowExpressionValues` is set to be `true`:
84
+
85
+ ```jsx
86
+ <div role={ROLE_BUTTON} onClick={() => {}} />;
87
+ // In case of a conditional expression, there should be literals on both sides of ternary operator
88
+ <div role={isButton ? "button" : "link"} onClick={() => {}} />;
89
+ ```
90
+
91
+ ### Succeed
92
+
93
+ ```jsx
94
+ <button onClick={() => {}} className="foo" />
95
+ <div className="foo" onClick={() => {}} role="button" />
96
+ <input type="text" onClick={() => {}} />
97
+ ```
98
+
99
+ ### Fail
100
+
101
+ ```jsx
102
+ <div onClick={() => {}} />
103
+ ```
104
+
105
+ ## Accessibility guidelines
106
+
107
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
108
+
109
+ ### Resources
110
+
111
+ - [WAI-ARIA `role` attribute](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)
112
+ - [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)
113
+ - [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
114
+ - [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)
@@ -0,0 +1,32 @@
1
+ # jsx-a11y/prefer-tag-over-role
2
+
3
+ <!-- end auto-generated rule header -->
4
+
5
+ Enforces using semantic DOM elements over the ARIA `role` property.
6
+
7
+ ## Rule details
8
+
9
+ This rule takes no arguments.
10
+
11
+ ### Succeed
12
+
13
+ ```jsx
14
+ <div>...</div>
15
+ <header>...</header>
16
+ <img alt="" src="image.jpg" />
17
+ ```
18
+
19
+ ### Fail
20
+
21
+ ```jsx
22
+ <div role="checkbox">
23
+ <div role="img">
24
+ ```
25
+
26
+ ## Accessibility guidelines
27
+
28
+ - [WAI-ARIA Roles model](https://www.w3.org/TR/wai-aria-1.0/roles)
29
+
30
+ ### Resources
31
+
32
+ - [MDN WAI-ARIA Roles](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles)
@@ -0,0 +1,31 @@
1
+ # jsx-a11y/role-has-required-aria-props
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Elements with ARIA roles must have all required attributes for that role.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <!-- Good: the checkbox role requires the aria-checked state -->
16
+ <span role="checkbox" aria-checked="false" aria-labelledby="foo" tabindex="0"></span>
17
+ ```
18
+
19
+ ### Fail
20
+
21
+ ```jsx
22
+ <!-- Bad: the checkbox role requires the aria-checked state -->
23
+ <span role="checkbox" aria-labelledby="foo" tabindex="0"></span>
24
+ ```
25
+
26
+ ## Accessibility guidelines
27
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
28
+
29
+ ### Resources
30
+ - [ARIA Spec, Roles](https://www.w3.org/TR/wai-aria/#roles)
31
+ - [Chrome Audit Rules, AX_ARIA_03](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_03)
@@ -0,0 +1,39 @@
1
+ # jsx-a11y/role-supports-aria-props
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Enforce that elements with explicit or implicit roles defined contain only `aria-*` properties supported by that `role`. Many ARIA attributes (states and properties) can only be used on elements with particular roles. Some elements have implicit roles, such as `<a href="#" />`, which will resolve to `role="link"`.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <!-- Good: the radiogroup role does support the aria-required property -->
16
+ <ul role="radiogroup" aria-required aria-labelledby="foo">
17
+ <li tabIndex="-1" role="radio" aria-checked="false">Rainbow Trout</li>
18
+ <li tabIndex="-1" role="radio" aria-checked="false">Brook Trout</li>
19
+ <li tabIndex="0" role="radio" aria-checked="true">Lake Trout</li>
20
+ </ul>
21
+ ```
22
+
23
+ ### Fail
24
+
25
+ ```jsx
26
+ <!-- Bad: the radio role does not support the aria-required property -->
27
+ <ul role="radiogroup" aria-labelledby="foo">
28
+ <li aria-required tabIndex="-1" role="radio" aria-checked="false">Rainbow Trout</li>
29
+ <li aria-required tabIndex="-1" role="radio" aria-checked="false">Brook Trout</li>
30
+ <li aria-required tabIndex="0" role="radio" aria-checked="true">Lake Trout</li>
31
+ </ul>
32
+ ```
33
+
34
+ ## Accessibility guidelines
35
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
36
+
37
+ ### Resources
38
+ - [ARIA Spec, States and Properties](https://www.w3.org/TR/wai-aria/#states_and_properties)
39
+ - [Chrome Audit Rules, AX_ARIA_10](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_10)
@@ -0,0 +1,30 @@
1
+ # jsx-a11y/scope
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ The `scope` prop should be used only on `<th>` elements.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <th scope="col" />
16
+ <th scope={scope} />
17
+ ```
18
+
19
+ ### Fail
20
+
21
+ ```jsx
22
+ <div scope />
23
+ ```
24
+
25
+ ## Accessibility guidelines
26
+ - [WCAG 1.3.1](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships)
27
+ - [WCAG 4.1.1](https://www.w3.org/WAI/WCAG21/Understanding/parsing)
28
+
29
+ ### Resources
30
+ - [axe-core, scope-attr-valid](https://dequeuniversity.com/rules/axe/3.5/scope-attr-valid)