@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,30 @@
1
+ # jsx-a11y/aria-proptypes
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ ARIA state and property values must be valid.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <!-- Good: the aria-hidden state is of type true/false -->
16
+ <span aria-hidden="true">foo</span>
17
+ ```
18
+
19
+ ### Fail
20
+ ```jsx
21
+ <!-- Bad: the aria-hidden state is of type true/false -->
22
+ <span aria-hidden="yes">foo</span>
23
+ ```
24
+
25
+ ## Accessibility guidelines
26
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
27
+
28
+ ### Resources
29
+ - [ARIA Spec, States and Properties](https://www.w3.org/TR/wai-aria/#states_and_properties)
30
+ - [Chrome Audit Rules, AX_ARIA_04](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_04)
@@ -0,0 +1,51 @@
1
+ # jsx-a11y/aria-role
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 use a valid, non-abstract ARIA role. A reference to role definitions can be found at [WAI-ARIA](https://www.w3.org/TR/wai-aria/#role_definitions) site.
8
+
9
+ ## Rule options
10
+
11
+ This rule takes one optional object argument of type object:
12
+
13
+ ```json
14
+ {
15
+ "rules": {
16
+ "jsx-a11y/aria-role": [ 2, {
17
+ "allowedInvalidRoles": ["text"],
18
+ "ignoreNonDOM": true
19
+ }],
20
+ }
21
+ }
22
+ ```
23
+
24
+ `allowedInvalidRules` is an optional string array of custom roles that should be allowed in addition to the ARIA spec, such as for cases when you [need to use a non-standard role](https://axesslab.com/text-splitting).
25
+
26
+ For the `ignoreNonDOM` option, this determines if developer created components are checked.
27
+
28
+ ### Succeed
29
+ ```jsx
30
+ <div role="button"></div> <!-- Good: "button" is a valid ARIA role -->
31
+ <div role={role}></div> <!-- Good: role is a variable & cannot be determined until runtime. -->
32
+ <div></div> <!-- Good: No ARIA role -->
33
+ <Foo role={role}></Foo> <!-- Good: ignoreNonDOM is set to true -->
34
+ ```
35
+
36
+ ### Fail
37
+
38
+ ```jsx
39
+ <div role="datepicker"></div> <!-- Bad: "datepicker" is not an ARIA role -->
40
+ <div role="range"></div> <!-- Bad: "range" is an _abstract_ ARIA role -->
41
+ <div role=""></div> <!-- Bad: An empty ARIA role is not allowed -->
42
+ <Foo role={role}></Foo> <!-- Bad: ignoreNonDOM is set to false or not set -->
43
+ ```
44
+
45
+ ## Accessibility guidelines
46
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
47
+
48
+ ### Resources
49
+ - [Chrome Audit Rules, AX_ARIA_01](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_01)
50
+ - [DPUB-ARIA roles](https://www.w3.org/TR/dpub-aria-1.0/)
51
+ - [MDN: Using ARIA: Roles, states, and properties](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques)
@@ -0,0 +1,30 @@
1
+ # jsx-a11y/aria-unsupported-elements
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `role` and/or `aria-*` props.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <!-- Good: the meta element should not be given any ARIA attributes -->
16
+ <meta charset="UTF-8" />
17
+ ```
18
+
19
+ ### Fail
20
+ ```jsx
21
+ <!-- Bad: the meta element should not be given any ARIA attributes -->
22
+ <meta charset="UTF-8" aria-hidden="false" />
23
+ ```
24
+
25
+ ## Accessibility guidelines
26
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
27
+
28
+ ### Resources
29
+ - [Chrome Audit Rules, AX_ARIA_12](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_12)
30
+ - [DPUB-ARIA roles](https://www.w3.org/TR/dpub-aria-1.0/)
@@ -0,0 +1,49 @@
1
+ # jsx-a11y/autocomplete-valid
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Ensure the autocomplete attribute is correct and suitable for the form field it is used with.
8
+
9
+ ## Rule options
10
+
11
+ This rule takes one optional object argument of type object:
12
+
13
+ ```
14
+ {
15
+ "rules": {
16
+ "jsx-a11y/autocomplete-valid": [ 2, {
17
+ "inputComponents": ["Input", "FormField"]
18
+ }],
19
+ }
20
+ }
21
+ ```
22
+
23
+ ### Succeed
24
+ ```jsx
25
+ <!-- Good: the autocomplete attribute is used according to the HTML specification -->
26
+ <input type="text" autocomplete="name" />
27
+
28
+ <!-- Good: MyInput is not listed in inputComponents -->
29
+ <MyInput autocomplete="incorrect" />
30
+ ```
31
+
32
+ ### Fail
33
+ ```jsx
34
+ <!-- Bad: the autocomplete attribute has an invalid value -->
35
+ <input type="text" autocomplete="incorrect" />
36
+
37
+ <!-- Bad: the autocomplete attribute is on an inappropriate input element -->
38
+ <input type="email" autocomplete="url" />
39
+
40
+ <!-- Bad: MyInput is listed in inputComponents -->
41
+ <MyInput autocomplete="incorrect" />
42
+ ```
43
+
44
+ ## Accessibility guidelines
45
+ - [WCAG 1.3.5](https://www.w3.org/WAI/WCAG21/Understanding/identify-input-purpose)
46
+
47
+ ### Resources
48
+ - [axe-core, autocomplete-valid](https://dequeuniversity.com/rules/axe/3.2/autocomplete-valid)
49
+ - [HTML 5.2, Autocomplete requirements](https://www.w3.org/TR/html52/sec-forms.html#autofilling-form-controls-the-autocomplete-attribute)
@@ -0,0 +1,28 @@
1
+ # jsx-a11y/click-events-have-key-events
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Enforce `onClick` is accompanied by at least one of the following: `onKeyUp`, `onKeyDown`, `onKeyPress`. Coding for the keyboard is important for users with physical disabilities who cannot use a mouse, AT compatibility, and screen reader users. This does not apply for interactive or hidden elements.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <div onClick={() => {}} onKeyDown={this.handleKeyDown} />
16
+ <div onClick={() => {}} onKeyUp={this.handleKeyUp} />
17
+ <div onClick={() => {}} onKeyPress={this.handleKeyPress} />
18
+ <button onClick={() => {}} />
19
+ <div onClick{() => {}} aria-hidden="true" />
20
+ ```
21
+
22
+ ### Fail
23
+ ```jsx
24
+ <div onClick={() => {}} />
25
+ ```
26
+
27
+ ## Accessibility guidelines
28
+ - [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)
@@ -0,0 +1,113 @@
1
+ # jsx-a11y/control-has-associated-label
2
+
3
+ 🚫 This rule is _disabled_ in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Enforce that a control (an interactive element) has a text label.
8
+
9
+ There are two supported ways to supply a control with a text label:
10
+
11
+ - Provide text content inside the element.
12
+ - Use the `aria-label` attribute on the element, with a text value.
13
+ - Use the `aria-labelledby` attribute on the element, and point the IDREF value to an element with an accessible label.
14
+ - Alternatively, with an `img` tag, you may use the `alt` attribute to supply a text description of the image.
15
+
16
+ The rule is permissive in the sense that it will assume that expressions will eventually provide a label. So an element like this will pass.
17
+
18
+ ```jsx
19
+ <button type="button">{maybeSomethingThatContainsALabel}</button>
20
+ ```
21
+
22
+ ## How do I resolve this error?
23
+
24
+ ### Case: I have a simple button that requires a label.
25
+
26
+ Provide text content in the `button` element.
27
+
28
+ ```jsx
29
+ <button type="button">Save</button>
30
+ ```
31
+
32
+ ### Case: I have an icon button and I don't want visible text.
33
+
34
+ Use the `aria-label` attribute and provide the text label as the value.
35
+
36
+ ```jsx
37
+ <button type="button" aria-label="Save" class="icon-save" />
38
+ ```
39
+
40
+ ### Case: The label for my element is already located on the page and I don't want to repeat the text in my source code.
41
+
42
+ Use the `aria-labelledby` attribute and point the IDREF value to an element with an accessible label.
43
+
44
+ ```jsx
45
+ <div id="js_1">Comment</div>
46
+ <textarea aria-labelledby="js_1"></textarea>
47
+ ```
48
+
49
+ ### Case: My label and input components are custom components, but I still want to require that they have an accessible text label.
50
+
51
+ You can configure the rule to be aware of your custom components. Refer to the Rule Details below.
52
+
53
+ ```jsx
54
+ <CustomInput label="Surname" type="text" value={value} />
55
+ ```
56
+
57
+ ## Rule options
58
+
59
+ This rule takes one optional object argument of type object:
60
+
61
+ ```json
62
+ {
63
+ "rules": {
64
+ "jsx-a11y/control-has-associated-label": [ 2, {
65
+ "labelAttributes": ["label"],
66
+ "controlComponents": ["CustomComponent"],
67
+ "ignoreElements": [
68
+ "audio",
69
+ "canvas",
70
+ "embed",
71
+ "input",
72
+ "textarea",
73
+ "tr",
74
+ "video",
75
+ ],
76
+ "ignoreRoles": [
77
+ "grid",
78
+ "listbox",
79
+ "menu",
80
+ "menubar",
81
+ "radiogroup",
82
+ "row",
83
+ "tablist",
84
+ "toolbar",
85
+ "tree",
86
+ "treegrid",
87
+ ],
88
+ "depth": 3,
89
+ }],
90
+ }
91
+ }
92
+ ```
93
+
94
+ - `labelAttributes` is a list of attributes to check on the control component and its children for a label. Use this if you have a custom component that uses a string passed on a prop to render an HTML `label`, for example.
95
+ - `controlComponents` is a list of custom React Components names that will render down to an interactive element.
96
+ - `ignoreElements` is an array of elements that should not be considered control (interactive) elements and therefore they do not require a text label.
97
+ - `ignoreRoles` is an array of ARIA roles that should not be considered control (interactive) roles and therefore they do not require a text label.
98
+ - `depth` (default 2, max 25) is an integer that determines how deep within a `JSXElement` the rule should look for text content or an element with a label to determine if the interactive element will have an accessible label.
99
+
100
+ ### Succeed
101
+ ```jsx
102
+ <button type="button" aria-label="Save" class="icon-save" />
103
+ ```
104
+
105
+ ### Fail
106
+ ```jsx
107
+ <button type="button" class="icon-save" />
108
+ ```
109
+
110
+ ## Accessibility guidelines
111
+ - [WCAG 1.3.1](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships)
112
+ - [WCAG 3.3.2](https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions)
113
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
@@ -0,0 +1,67 @@
1
+ # jsx-a11y/heading-has-content
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Enforce that heading elements (`h1`, `h2`, etc.) have content and that the content is accessible to screen readers. Accessible means that it is not hidden using the `aria-hidden` prop. Refer to the references to learn about why this is important.
8
+
9
+ ## Rule options
10
+
11
+ This rule takes one optional object argument of type object:
12
+
13
+ ```json
14
+ {
15
+ "rules": {
16
+ "jsx-a11y/heading-has-content": [ 2, {
17
+ "components": [ "MyHeading" ],
18
+ }],
19
+ }
20
+ }
21
+ ```
22
+
23
+ For the `components` option, these strings determine which JSX elements (**always including** `<h1>` thru `<h6>`) should be checked for having content. This is a good use case when you have a wrapper component that simply renders an `h1` element (like in React):
24
+
25
+
26
+ ```js
27
+ // Header.js
28
+ const Header = props => {
29
+ return (
30
+ <h1 {...props}>{ props.children }</h1>
31
+ );
32
+ }
33
+
34
+ ...
35
+
36
+ // CreateAccount.js (for example)
37
+ ...
38
+ return (
39
+ <Header>Create Account</Header>
40
+ );
41
+ ```
42
+
43
+ #### Bad
44
+ ```jsx
45
+ function Foo(props) {
46
+ return <label {...props} />
47
+ }
48
+ ```
49
+
50
+ ### Succeed
51
+ ```jsx
52
+ <h1>Heading Content!</h1>
53
+ <h1><TextWrapper /><h1>
54
+ <h1 dangerouslySetInnerHTML={{ __html: 'foo' }} />
55
+ ```
56
+
57
+ ### Fail
58
+ ```jsx
59
+ <h1 />
60
+ <h1><TextWrapper aria-hidden />
61
+ ```
62
+
63
+ ## Accessibility guidelines
64
+ - [WCAG 2.4.6](https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-descriptive.html)
65
+
66
+ ### Resources
67
+ - [axe-core, empty-heading](https://dequeuniversity.com/rules/axe/3.2/empty-heading)
@@ -0,0 +1,31 @@
1
+ # jsx-a11y/html-has-lang
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ <html> elements must have the lang prop. This rule is largely superseded by the [`lang` rule](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/lang.md).
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <html lang="en">
16
+ <html lang="en-US">
17
+ <html lang={language}>
18
+ ```
19
+
20
+ ### Fail
21
+
22
+ ```jsx
23
+ <html>
24
+ ```
25
+
26
+ ## Accessibility guidelines
27
+ - [WCAG 3.1.1](https://www.w3.org/WAI/WCAG21/Understanding/language-of-page)
28
+
29
+ ### Resources
30
+ - [axe-core, html-has-lang](https://dequeuniversity.com/rules/axe/3.2/html-has-lang)
31
+ - [axe-core, html-lang-valid](https://dequeuniversity.com/rules/axe/3.2/html-lang-valid)
@@ -0,0 +1,37 @@
1
+ # jsx-a11y/iframe-has-title
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ `<iframe>` elements must have a unique title property to indicate its content to the user.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <iframe title="This is a unique title" />
16
+ <iframe title={uniqueTitle} />
17
+ ```
18
+
19
+ ### Fail
20
+ ```jsx
21
+ <iframe />
22
+ <iframe {...props} />
23
+ <iframe title="" />
24
+ <iframe title={''} />
25
+ <iframe title={``} />
26
+ <iframe title={undefined} />
27
+ <iframe title={false} />
28
+ <iframe title={true} />
29
+ <iframe title={42} />
30
+ ```
31
+
32
+ ## Accessibility guidelines
33
+ - [WCAG 2.4.1](https://www.w3.org/WAI/WCAG21/Understanding/bypass-blocks)
34
+ - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
35
+
36
+ ### Resources
37
+ - [axe-core, frame-title](https://dequeuniversity.com/rules/axe/3.2/frame-title)
@@ -0,0 +1,48 @@
1
+ # jsx-a11y/img-redundant-alt
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Enforce img alt attribute does not contain the word image, picture, or photo. Screen readers already announce `img` elements as an image. There is no need to use words such as *image*, *photo*, and/or *picture*.
8
+
9
+ ## Rule options
10
+
11
+ This rule takes one optional object argument of type object:
12
+
13
+ ```json
14
+ {
15
+ "rules": {
16
+ "jsx-a11y/img-redundant-alt": [ 2, {
17
+ "components": [ "Image" ],
18
+ "words": [ "Bild", "Foto" ],
19
+ }],
20
+ }
21
+ }
22
+ ```
23
+
24
+ For the `components` option, these strings determine which JSX elements (**always including** `<img>`) should be checked for having redundant words in the `alt` prop value . This is a good use case when you have a wrapper component that simply renders an `img` element (like in React).
25
+
26
+ For the `words` option, these strings can be used to specify custom words that should be checked for in the alt prop, including `image`, `photo`, and `picture`. Useful for specifying words in other languages.
27
+
28
+ The rule will first check if `aria-hidden` is true to determine whether to enforce the rule. If the image is hidden, then rule will always succeed.
29
+
30
+ ### Succeed
31
+ ```jsx
32
+ <img src="foo" alt="Foo eating a sandwich." />
33
+ <img src="bar" aria-hidden alt="Picture of me taking a photo of an image" /> // Will pass because it is hidden.
34
+ <img src="baz" alt={`Baz taking a ${photo}`} /> // This is valid since photo is a variable name.
35
+ ```
36
+
37
+ ### Fail
38
+ ```jsx
39
+ <img src="foo" alt="Photo of foo being weird." />
40
+ <img src="bar" alt="Image of me at a bar!" />
41
+ <img src="baz" alt="Picture of baz fixing a bug." />
42
+ ```
43
+
44
+ ## Accessibility guidelines
45
+ General best practice (reference resources)
46
+
47
+ ### Resources
48
+ - [WebAIM, Alternative Text](https://webaim.org/techniques/alttext/)
@@ -0,0 +1,156 @@
1
+ # jsx-a11y/interactive-supports-focus
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Elements with an interactive role and interaction handlers (mouse or key press) must be focusable.
8
+
9
+ ## How do I resolve this error?
10
+
11
+ ### Case: I got the error "Elements with the '${role}' interactive role must be tabbable". How can I fix this?
12
+
13
+ This element is a stand-alone control like a button, a link or a form element. A user should be able to reach this element by pressing the tab key on their keyboard.
14
+
15
+ Add the `tabIndex` property to your component. A value of zero indicates that this element can be tabbed to.
16
+
17
+ ```jsx
18
+ <div
19
+ role="button"
20
+ tabIndex={0} />
21
+ ```
22
+
23
+ -- or --
24
+
25
+ Replace the component with one that renders semantic html element like `<button>`, `<a href>` or `<input>` -- whichever fits your purpose.
26
+
27
+ Generally buttons, links and form elements should be reachable via tab key presses. An element that can be tabbed to is said to be in the _tab ring_.
28
+
29
+ ### Case: I got the error "Elements with the '${role}' interactive role must be focusable". How can I fix this?
30
+
31
+ This element is part of a group of buttons, links, menu items, etc. Or this element is part of a composite widget. Composite widgets prescribe standard [keyboard interaction patterns](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav). Within a group of similar elements -- like a button bar -- or within a composite widget, elements that can be focused are given a tabindex of -1. This makes the element _focusable_ but not _tabbable_. Generally one item in a group should have a tabindex of zero so that a user can tab to the component. Once an element in the component has focus, your key management behaviors will control traversal within the component's pieces. As the UI author, you will need to implement the key handling behaviors such as listening for traversal key (up/down/left/right) presses and moving the page focus between the focusable elements in your widget.
32
+
33
+ ```jsx
34
+ <div role="menu">
35
+ <div role="menuitem" tabIndex="0">Open</div>
36
+ <div role="menuitem" tabIndex="-1">Save</div>
37
+ <div role="menuitem" tabIndex="-1">Close</div>
38
+ </div>
39
+ ```
40
+
41
+ In the example above, the first item in the group can be tabbed to. The developer provides the ability to traverse to the subsequent items via the up/down/left/right arrow keys. Traversing via arrow keys is not provided by the browser or the assistive technology. See [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav) for information about established traversal behaviors for various UI widgets.
42
+
43
+ ### Case: This element is not a button, link, menuitem, etc. It is catching bubbled events from elements that it contains
44
+
45
+ If your element is catching bubbled click or key events from descendant elements, then the proper role for this element is `presentation`.
46
+
47
+ ```jsx
48
+ <div
49
+ onClick={onClickHandler}
50
+ role="presentation">
51
+ <button>Save</button>
52
+ </div>
53
+ ```
54
+
55
+ 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.
56
+
57
+ ## Rule options
58
+
59
+ This rule takes an options object with the key `tabbable`. The value is an array of interactive ARIA roles that should be considered tabbable, not just focusable. Any interactive role not included in this list will be flagged as needing to be focusable (tabindex of -1).
60
+
61
+ ```js
62
+ {
63
+ 'jsx-a11y/interactive-supports-focus': [
64
+ 'error',
65
+ {
66
+ tabbable: [
67
+ 'button',
68
+ 'checkbox',
69
+ 'link',
70
+ 'searchbox',
71
+ 'spinbutton',
72
+ 'switch',
73
+ 'textbox',
74
+ ],
75
+ },
76
+ ]
77
+ }
78
+ ```
79
+
80
+ The recommended options list interactive roles that act as form elements. Generally, elements with a role like `menuitem` are a part of a composite widget. Focus in a composite widget is controlled and moved programmatically to satisfy the prescribed [keyboard interaction pattern](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav) for the widget.
81
+
82
+ The list of possible values includes:
83
+
84
+ ```js
85
+ [
86
+ 'button',
87
+ 'checkbox',
88
+ 'columnheader',
89
+ 'combobox',
90
+ 'grid',
91
+ 'gridcell',
92
+ 'link',
93
+ 'listbox',
94
+ 'menu',
95
+ 'menubar',
96
+ 'menuitem',
97
+ 'menuitemcheckbox',
98
+ 'menuitemradio',
99
+ 'option',
100
+ 'progressbar',
101
+ 'radio',
102
+ 'radiogroup',
103
+ 'row',
104
+ 'rowheader',
105
+ 'searchbox',
106
+ 'slider',
107
+ 'spinbutton',
108
+ 'switch',
109
+ 'tab',
110
+ 'tablist',
111
+ 'textbox',
112
+ 'toolbar',
113
+ 'tree',
114
+ 'treegrid',
115
+ 'treeitem',
116
+ 'doc-backlink',
117
+ 'doc-biblioref',
118
+ 'doc-glossref',
119
+ 'doc-noteref',
120
+ ]
121
+ ```
122
+
123
+ ### Succeed
124
+
125
+ ```jsx
126
+ <!-- Good: div with onClick attribute is hidden from screen reader -->
127
+ <div aria-hidden onClick={() => void 0} />
128
+ <!-- Good: span with onClick attribute is in the tab order -->
129
+ <span onClick="doSomething();" tabIndex="0" role="button">Click me!</span>
130
+ <!-- Good: span with onClick attribute may be focused programmatically -->
131
+ <span onClick="doSomething();" tabIndex="-1" role="menuitem">Click me too!</span>
132
+ <!-- Good: anchor element with href is inherently focusable -->
133
+ <a href="javascript:void(0);" onClick="doSomething();">Click ALL the things!</a>
134
+ <!-- Good: buttons are inherently focusable -->
135
+ <button onClick="doSomething();">Click the button :)</button>
136
+ ```
137
+
138
+ ### Fail
139
+
140
+ ```jsx
141
+ <!-- Bad: span with onClick attribute has no tabindex -->
142
+ <span onclick="submitForm();" role="button">Submit</span>
143
+ <!-- Bad: anchor element without href is not focusable -->
144
+ <a onclick="showNextPage();" role="button">Next page</a>
145
+ ```
146
+
147
+ ## Accessibility guidelines
148
+
149
+ - [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)
150
+
151
+ ### Resources
152
+
153
+ - [Chrome Audit Rules, AX_FOCUS_02](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_02)
154
+ - [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)
155
+ - [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
156
+ - [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)