0.2.0 - Mid migration

This commit is contained in:
Daniel Mason 2022-04-25 14:47:15 +12:00
parent 139e6a915e
commit 7e38fdbd7d
42393 changed files with 5358157 additions and 62 deletions

View file

@ -0,0 +1,26 @@
# [Deprecated] accessible-emoji
Emoji have become a common way of communicating content to the end user. To a person using a screenreader, however, they may not be aware that this content is there at all. By wrapping the emoji in a `<span>`, giving it the `role="img"`, and providing a useful description in `aria-label`, the screenreader will treat the emoji as an image in the accessibility tree with an accessible name for the end user.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<span role="img" aria-label="Snowman">&#9731;</span>
<span role="img" aria-label="Panda">🐼</span>
<span role="img" aria-labelledby="panda1">🐼</span>
```
### Fail
```jsx
<span>🐼</span>
<i role="img" aria-label="Panda">🐼</i>
```
## Accessibility guidelines
- [WCAG 1.1.1](https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html)
### Resources
- [Léonie Watson, Accessible Emoji](http://tink.uk/accessible-emoji/)

View file

@ -0,0 +1,146 @@
# alt-text
Enforce that all elements that require alternative text have meaningful information to relay back to the end user. This is a critical component of accessibility for screen reader users in order for them to understand the content's purpose on the page. By default, this rule checks for alternative text on the following elements: `<img>`, `<area>`, `<input type="image">`, and `<object>`.
## How to resolve
### `<img>`
An `<img>` must have the `alt` prop set with meaningful text or as an empty string to indicate that it is an image for decoration.
For images that are being used as icons for a button or control, the `alt` prop should be set to an empty string (`alt=""`).
```jsx
<button>
<img src="icon.png" alt="" />
Save
</button>
```
The content of an `alt` attribute is used to calculate the accessible label of an element, whereas the text content is used to produce a label for the element. For this reason, adding a label to an icon can produce a confusing or duplicated label on a control that already has appropriate text content.
### `<object>`
Add alternative text to all embedded `<object>` elements using either inner text, setting the `title` prop, or using the `aria-label` or `aria-labelledby` props.
### `<input type="image">`
All `<input type="image">` elements must have a non-empty `alt` prop set with a meaningful description of the image or have the `aria-label` or `aria-labelledby` props set.
### `<area>`
All clickable `<area>` elements within an image map have an `alt`, `aria-label` or `aria-labelledby` prop that describes the purpose of the link.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/alt-text": [ 2, {
"elements": [ "img", "object", "area", "input[type=\"image\"]" ],
"img": ["Image"],
"object": ["Object"],
"area": ["Area"],
"input[type=\"image\"]": ["InputImage"]
}],
}
}
```
The `elements` option is a whitelist for DOM elements to check for alternative text. If an element is removed from the default set of elements (noted above), any custom components for that component will also be ignored. In order to indicate any custom wrapper components that should be checked, you can map the DOM element to an array of JSX custom components. This is a good use case when you have a wrapper component that simply renders an `img` element, for instance (like in React):
```jsx
// Image.js
const Image = props => {
const {
alt,
...otherProps
} = props;
return (
<img alt={alt} {...otherProps} />
);
}
...
// Header.js (for example)
...
return (
<header>
<Image alt="Logo" src="logo.jpg" />
</header>
);
```
Note that passing props as spread attribute without explicitly the necessary accessibility props defined will cause this rule to fail. Explicitly pass down the set of props needed for rule to pass. Use `Image` component above as a reference for destructuring and applying the prop. **It is a good thing to explicitly pass props that you expect to be passed for self-documentation.** For example:
#### Bad
```jsx
function Foo(props) {
return <img {...props} />
}
```
#### Good
```jsx
function Foo({ alt, ...props}) {
return <img alt={alt} {...props} />
}
// OR
function Foo(props) {
const {
alt,
...otherProps
} = props;
return <img alt={alt} {...otherProps} />
}
```
### Succeed
```jsx
<img src="foo" alt="Foo eating a sandwich." />
<img src="foo" alt={"Foo eating a sandwich."} />
<img src="foo" alt={altText} />
<img src="foo" alt={`${person} smiling`} />
<img src="foo" alt="" />
<object aria-label="foo" />
<object aria-labelledby="id1" />
<object>Meaningful description</object>
<object title="An object" />
<area aria-label="foo" />
<area aria-labelledby="id1" />
<area alt="This is descriptive!" />
<input type="image" alt="This is descriptive!" />
<input type="image" aria-label="foo" />
<input type="image" aria-labelledby="id1" />
```
### Fail
```jsx
<img src="foo" />
<img {...props} />
<img {...props} alt /> // Has no value
<img {...props} alt={undefined} /> // Has no value
<img {...props} alt={`${undefined}`} /> // Has no value
<img src="foo" role="presentation" /> // Avoid ARIA if it can be achieved without
<img src="foo" role="none" /> // Avoid ARIA if it can be achieved without
<object {...props} />
<area {...props} />
<input type="image" {...props} />
```
## Accessibility guidelines
- [WCAG 1.1.1](https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html)
### Resources
- [axe-core, object-alt](https://dequeuniversity.com/rules/axe/3.2/object-alt)
- [axe-core, image-alt](https://dequeuniversity.com/rules/axe/3.2/image-alt)
- [axe-core, input-image-alt](https://dequeuniversity.com/rules/axe/3.2/input-image-alt)
- [axe-core, area-alt](https://dequeuniversity.com/rules/axe/3.2/area-alt)

View file

@ -0,0 +1,56 @@
# anchor-has-content
Enforce that anchors 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.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/anchor-has-content": [ 2, {
"components": [ "Anchor" ],
}],
}
}
```
For the `components` option, these strings determine which JSX elements (**always including** `<a>`) should be checked for having content. This is a good use case when you have a wrapper component that simply renders an `a` element (like in React):
```js
// Anchor.js
const Anchor = props => {
return (
<a {...props}>{ props.children }</a>
);
}
...
// CreateAccount.js (for example)
...
return (
<Anchor>Create Account</Anchor>
);
```
### Succeed
```jsx
<a>Anchor Content!</a>
<a><TextWrapper /><a>
<a dangerouslySetInnerHTML={{ __html: 'foo' }} />
```
### Fail
```jsx
<a />
<a><TextWrapper aria-hidden /></a>
```
## Accessibility guidelines
- [WCAG 2.4.4](https://www.w3.org/WAI/WCAG21/Understanding/link-purpose-in-context)
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [axe-core, link-name](https://dequeuniversity.com/rules/axe/3.2/link-name)

View file

@ -0,0 +1,226 @@
# anchor-is-valid
The HTML `<a>` element, with a valid `href` attribute, is formally defined as representing a **hyperlink**. That is, a link between one HTML document and another, or between one location inside an HTML document and another location inside the same document.
In fact, the interactive, underlined `<a>` element has become so synonymous with web navigation that this expectation has become entrenched inside browsers, assistive technologies such as screen readers and in how people generally expect the internet to behave. In short, anchors should navigate.
The use of JavaScript frameworks and libraries, like _React_, has made it very easy to add or subtract functionality from the standard HTML elements. This has led to _anchors_ often being used in applications based on how they look and function instead of what they represent.
Whilst it is possible, for example, to turn the `<a>` element into a fully functional `<button>` element with ARIA, the native user agent implementations of HTML elements are to be preferred over custom ARIA solutions.
## How do I resolve this error?
### Case: I want to perform an action and need a clickable UI element
The native user agent implementations of the `<a>` and `<button>` elements not only differ in how they look and how they act when activated, but also in how the user is expected to interact with them. Both are perfectly clickable when using a mouse, but keyboard users expect `<a>` to activate on `enter` only and `<button>` to activate on _both_ `enter` and `space`.
This is exacerbated by the expectation sighted users have of how _buttons_ and _anchors_ work based on their appearance. Therefore we find that using _anchors_ as _buttons_ can easily create confusion without a relatively complicated ARIA and CSS implementation that only serves to create an element HTML already offers and browsers already implement fully accessibly.
We are aware that sometimes _anchors_ are used instead of _buttons_ to achieve a specific visual design. When using the `<button>` element this can still be achieved with styling but, due to the meaning many people attach to the standard underlined `<a>` due its appearance, please reconsider this in the design.
Consider the following:
```jsx
<a href="javascript:void(0)" onClick={foo} >Perform action</a>
<a href="#" onClick={foo} >Perform action</a>
<a onClick={foo} >Perform action</a>
```
All these _anchor_ implementations indicate that the element is only used to execute JavaScript code. All the above should be replaced with:
```jsx
<button onClick={foo} >Perform action</button>
```
### Case: I want navigable links
An `<a>` element without an `href` attribute no longer functions as a hyperlink. That means that it can no longer accept keyboard focus or be clicked on. The documentation for [no-noninteractive-tabindex](no-noninteractive-tabindex.md) explores this further. Preferably use another element (such as `div` or `span`) for display of text.
To properly function as a hyperlink, the `href` attribute should be present and also contain a valid _URL_. _JavaScript_ strings, empty values or using only **#** are not considered valid `href` values.
Valid `href` attributes values are:
```jsx
<a href="/some/valid/uri" >Navigate to page</a>
<a href="/some/valid/uri#top" >Navigate to page and location</a>
<a href="#top" >Navigate to internal page location</a>
```
### Case: I need the HTML to be interactive, don't I need to use an a tag for that?
An `<a>` tag is not inherently interactive. Without an href attribute, it really is no different to a `<div>`.
Let's look at an example that is not accessible by all users:
```jsx
<a
className={'thing'}
onMouseEnter={() => this.setState({showSomething: true})}>
{label}
</a>
```
If you need to create an interface element that the user can click on, consider using a button:
```jsx
<button
className={'thing'}
onClick={() => this.setState({showSomething: true})}>
{label}
</button>
```
If you want to navigate while providing the user with extra functionality, for example in the `onMouseEnter` event, use an anchor with an `href` attribute containing a URL or path as its value.
```jsx
<a
href={someValidPath}
className={'thing'}
onMouseEnter={() => this.setState({showSomething: true})}>
{label}
</a>
```
If you need to create an interface element that the user can mouse over or mouse out of, consider using a div element. In this case, you may need to apply a role of presentation or an interactive role. Interactive ARIA roles include `button`, `link`, `checkbox`, `menuitem`, `menuitemcheckbox`, `menuitemradio`, `option`, `radio`, `searchbox`, `switch` and `textbox`.
```jsx
<div
role="menuitem"
className={'thing'}
onClick={() => this.setState({showSomething: true})}>
onMouseEnter={() => this.setState({showSomething: true})}>
{label}
</div>
```
In the example immediately above an `onClick` event handler was added to provide the same experience mouse users enjoy to keyboard-only and touch-screen users. Never fully rely on mouse events alone to expose functionality.
### Case: I understand the previous cases but still need an element resembling a link that is purely clickable
We recommend, without reserve, that elements resembling anchors should navigate. This will provide a superior user experience to a larger group of users out there.
However, we understand that developers are not always in total control of the visual design of web applications. In cases where it is imperative to provide an element resembling an anchor that purely acts as a click target with no navigation as result, we would like to recommend a compromise.
Again change the element to a `<button>`:
```jsx
<button
type="button"
className="link-button"
onClick={() => this.setState({showSomething: true})}>
Press me, I look like a link
</button>
```
Then use styling to change its appearance to that of a link:
```css
.link-button {
background-color: transparent;
border: none;
cursor: pointer;
text-decoration: underline;
display: inline;
margin: 0;
padding: 0;
}
.link-button:hover,
.link-button:focus {
text-decoration: none;
}
```
This button element can now also be used inline in text.
Once again we stress that this is an inferior implementation and some users will encounter difficulty to use your website, however, it will allow a larger group of people to interact with your website than the alternative of ignoring the rule's warning.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/anchor-is-valid": [ "error", {
"components": [ "Link" ],
"specialLink": [ "hrefLeft", "hrefRight" ],
"aspects": [ "noHref", "invalidHref", "preferButton" ]
}]
}
}
```
For the `components` option, these strings determine which JSX elements (**always including** `<a>`) should be checked for the props designated in the `specialLink` options (**always including** `href`). This is a good use case when you have a wrapper component that simply renders an `<a>` element (like in React):
```js
// Link.js
const Link = props => <a {...props}>A link</a>;
...
// NavBar.js (for example)
...
return (
<nav>
<Link href="/home" />
</nav>
);
```
For the `aspects` option, these strings determine which sub-rules are run. This allows omission of certain error types in restrictive environments.
- `noHref`: Checks whether an anchor contains an `href` attribute.
- `invalidHref`: Checks if a given `href` value is valid.
- `preferButton`: Checks if anchors have been used as buttons.
The option can be used on its own or with the `components` and `specialLink` options.
If omitted, all sub-rule aspects will be run by default. This is the recommended configuration for all cases except where the rule becomes unusable due to well founded restrictions.
The option must contain at least one `aspect`.
### Succeed
```jsx
<a href="https://github.com" />
<a href="#section" />
<a href="foo" />
<a href="/foo/bar" />
<a href={someValidPath} />
<a href="https://github.com" onClick={foo} />
<a href="#section" onClick={foo} />
<a href="foo" onClick={foo} />
<a href="/foo/bar" onClick={foo} />
<a href={someValidPath} onClick={foo} />
```
### Fail
Anchors should be a button:
```jsx
<a onClick={foo} />
<a href="#" onClick={foo} />
<a href={"#"} onClick={foo} />
<a href={`#`} onClick={foo} />
<a href="javascript:void(0)" onClick={foo} />
<a href={"javascript:void(0)"} onClick={foo} />
<a href={`javascript:void(0)`} onClick={foo} />
```
Missing `href` attribute:
```jsx
<a />
<a href={undefined} />
<a href={null} />
```
Invalid `href` attribute:
```jsx
<a href="#" />
<a href={"#"} />
<a href={`#`} />
<a href="javascript:void(0)" />
<a href={"javascript:void(0)"} />
<a href={`javascript:void(0)`} />
```
## Accessibility guidelines
- [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)
### Resources
- [WebAIM - Introduction to Links and Hypertext](http://webaim.org/techniques/hypertext/)
- [Links vs. Buttons in Modern Web Applications](https://marcysutton.com/links-vs-buttons-in-modern-web-applications/)
- [Using ARIA - Notes on ARIA use in HTML](https://www.w3.org/TR/using-aria/#NOTES)

View file

@ -0,0 +1,49 @@
# aria-activedescendant-has-tabindex
`aria-activedescendant` is used to manage focus within a [composite widget](https://www.w3.org/TR/wai-aria/#composite).
The element with the attribute `aria-activedescendant` retains the active document
focus; it indicates which of its child elements has secondary focus by assigning
the ID of that element to the value of `aria-activedescendant`. This pattern is
used to build a widget like a search typeahead select list. The search input box
retains document focus so that the user can type in the input. If the down arrow
key is pressed and a search suggestion is highlighted, the ID of the suggestion
element will be applied as the value of `aria-activedescendant` on the input
element.
Because an element with `aria-activedescendant` must be tabbable, it must either
have an inherent `tabIndex` of zero or declare a `tabIndex` of zero with the `tabIndex`
attribute.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<CustomComponent />
<CustomComponent aria-activedescendant={someID} />
<CustomComponent aria-activedescendant={someID} tabIndex={0} />
<CustomComponent aria-activedescendant={someID} tabIndex={-1} />
<div />
<input />
<div tabIndex={0} />
<div aria-activedescendant={someID} tabIndex={0} />
<div aria-activedescendant={someID} tabIndex="0" />
<div aria-activedescendant={someID} tabIndex={1} />
<input aria-activedescendant={someID} />
<input aria-activedescendant={someID} tabIndex={0} />
```
### Fail
```jsx
<div aria-activedescendant={someID} />
<div aria-activedescendant={someID} tabIndex={-1} />
<div aria-activedescendant={someID} tabIndex="-1" />
<input aria-activedescendant={someID} tabIndex={-1} />
```
## Accessibility guidelines
General best practice (reference resources)
### Resources
- [MDN, Using the aria-activedescendant attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-activedescendant_attribute)

View file

@ -0,0 +1,25 @@
# aria-props
Elements cannot use an invalid ARIA attribute. This will fail if it finds an `aria-*` property that is not listed in [WAI-ARIA States and Properties spec](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties).
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<!-- Good: Labeled using correctly spelled aria-labelledby -->
<div id="address_label">Enter your address</div>
<input aria-labelledby="address_label">
```
### Fail
```jsx
<!-- Bad: Labeled using incorrectly spelled aria-labeledby -->
<div id="address_label">Enter your address</div>
<input aria-labeledby="address_label">
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)

View file

@ -0,0 +1,26 @@
# aria-proptypes
ARIA state and property values must be valid.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<!-- Good: the aria-hidden state is of type true/false -->
<span aria-hidden="true">foo</span>
```
### Fail
```jsx
<!-- Bad: the aria-hidden state is of type true/false -->
<span aria-hidden="yes">foo</span>
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [ARIA Spec, States and Properties](https://www.w3.org/TR/wai-aria/#states_and_properties)
- [Chrome Audit Rules, AX_ARIA_04](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_04)

View file

@ -0,0 +1,43 @@
# aria-role
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.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/aria-role": [ 2, {
"ignoreNonDOM": true
}],
}
}
```
For the `ignoreNonDOM` option, this determines if developer created components are checked.
### Succeed
```jsx
<div role="button"></div> <!-- Good: "button" is a valid ARIA role -->
<div role={role}></div> <!-- Good: role is a variable & cannot be determined until runtime. -->
<div></div> <!-- Good: No ARIA role -->
<Foo role={role}></Foo> <!-- Good: ignoreNonDOM is set to true -->
```
### Fail
```jsx
<div role="datepicker"></div> <!-- Bad: "datepicker" is not an ARIA role -->
<div role="range"></div> <!-- Bad: "range" is an _abstract_ ARIA role -->
<div role=""></div> <!-- Bad: An empty ARIA role is not allowed -->
<Foo role={role}></Foo> <!-- Bad: ignoreNonDOM is set to false or not set -->
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [Chrome Audit Rules, AX_ARIA_01](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_01)
- [DPUB-ARIA roles](https://www.w3.org/TR/dpub-aria-1.0/)

View file

@ -0,0 +1,26 @@
# aria-unsupported-elements
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.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<!-- Good: the meta element should not be given any ARIA attributes -->
<meta charset="UTF-8" />
```
### Fail
```jsx
<!-- Bad: the meta element should not be given any ARIA attributes -->
<meta charset="UTF-8" aria-hidden="false" />
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [Chrome Audit Rules, AX_ARIA_12](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_12)
- [DPUB-ARIA roles](https://www.w3.org/TR/dpub-aria-1.0/)

View file

@ -0,0 +1,45 @@
# autocomplete-valid
Ensure the autocomplete attribute is correct and suitable for the form field it is used with.
## Rule details
This rule takes one optional object argument of type object:
```
{
"rules": {
"jsx-a11y/autocomplete-valid": [ 2, {
"inputComponents": ["Input", "FormField"]
}],
}
}
```
### Succeed
```jsx
<!-- Good: the autocomplete attribute is used according to the HTML specification -->
<input type="text" autocomplete="name" />
<!-- Good: MyInput is not listed in inputComponents -->
<MyInput autocomplete="incorrect" />
```
### Fail
```jsx
<!-- Bad: the autocomplete attribute has an invalid value -->
<input type="text" autocomplete="incorrect" />
<!-- Bad: the autocomplete attribute is on an inappropriate input element -->
<input type="email" autocomplete="url" />
<!-- Bad: MyInput is listed in inputComponents -->
<MyInput autocomplete="incorrect" />
```
## Accessibility guidelines
- [WCAG 1.3.5](https://www.w3.org/WAI/WCAG21/Understanding/identify-input-purpose)
### Resources
- [axe-core, autocomplete-valid](https://dequeuniversity.com/rules/axe/3.2/autocomplete-valid)
- [HTML 5.2, Autocomplete requirements](https://www.w3.org/TR/html52/sec-forms.html#autofilling-form-controls-the-autocomplete-attribute)

View file

@ -0,0 +1,24 @@
# click-events-have-key-events
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 screenreader users. This does not apply for interactive or hidden elements.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<div onClick={() => {}} onKeyDown={this.handleKeyDown} />
<div onClick={() => {}} onKeyUp={this.handleKeyUp} />
<div onClick={() => {}} onKeyPress={this.handleKeyPress} />
<button onClick={() => {}} />
<div onClick{() => {}} aria-hidden="true" />
```
### Fail
```jsx
<div onClick={() => {}} />
```
## Accessibility guidelines
- [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)

View file

@ -0,0 +1,109 @@
# control-has-associated-label
Enforce that a control (an interactive element) has a text label.
There are two supported ways to supply a control with a text label:
- Provide text content inside the element.
- Use the `aria-label` attribute on the element, with a text value.
- Use the `aria-labelledby` attribute on the element, and point the IDREF value to an element with an accessible label.
- Alternatively, with an `img` tag, you may use the `alt` attribute to supply a text description of the image.
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.
```jsx
<button type="button">{maybeSomethingThatContainsALabel}</button>
```
## How do I resolve this error?
### Case: I have a simple button that requires a label.
Provide text content in the `button` element.
```jsx
<button type="button">Save</button>
```
### Case: I have an icon button and I don't want visible text.
Use the `aria-label` attribute and provide the text label as the value.
```jsx
<button type="button" aria-label="Save" class="icon-save" />
```
### 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.
Use the `aria-labelledby` attribute and point the IDREF value to an element with an accessible label.
```jsx
<div id="js_1">Comment</div>
<textarea aria-labelledby="js_1"></textarea>
```
### Case: My label and input components are custom components, but I still want to require that they have an accessible text label.
You can configure the rule to be aware of your custom components. Refer to the Rule Details below.
```jsx
<CustomInput label="Surname" type="text" value={value} />
```
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/control-has-associated-label": [ 2, {
"labelAttributes": ["label"],
"controlComponents": ["CustomComponent"],
"ignoreElements": [
"audio",
"canvas",
"embed",
"input",
"textarea",
"tr",
"video",
],
"ignoreRoles": [
"grid",
"listbox",
"menu",
"menubar",
"radiogroup",
"row",
"tablist",
"toolbar",
"tree",
"treegrid",
],
"depth": 3,
}],
}
}
```
- `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.
- `controlComponents` is a list of custom React Components names that will render down to an interactive element.
- `ignoreElements` is an array of elements that should not be considered control (interactive) elements and therefore they do not require a text label.
- `ignoreRoles` is an array of ARIA roles that should not be considered control (interactive) roles and therefore they do not require a text label.
- `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.
### Succeed
```jsx
<button type="button" aria-label="Save" class="icon-save" />
```
### Fail
```jsx
<button type="button" class="icon-save" />
```
## Accessibility guidelines
- [WCAG 1.3.1](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships)
- [WCAG 3.3.2](https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions)
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)

View file

@ -0,0 +1,63 @@
# heading-has-content
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.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/heading-has-content": [ 2, {
"components": [ "MyHeading" ],
}],
}
}
```
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):
```js
// Header.js
const Header = props => {
return (
<h1 {...props}>{ props.children }</h1>
);
}
...
// CreateAccount.js (for example)
...
return (
<Header>Create Account</Header>
);
```
#### Bad
```jsx
function Foo(props) {
return <label {...props} />
}
```
### Succeed
```jsx
<h1>Heading Content!</h1>
<h1><TextWrapper /><h1>
<h1 dangerouslySetInnerHTML={{ __html: 'foo' }} />
```
### Fail
```jsx
<h1 />
<h1><TextWrapper aria-hidden />
```
## Accessibility guidelines
- [WCAG 2.4.6](https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-descriptive.html)
### Resources
- [axe-core, empty-heading](https://dequeuniversity.com/rules/axe/3.2/empty-heading)

View file

@ -0,0 +1,27 @@
# html-has-lang
<html> elements must have the lang prop.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<html lang="en">
<html lang="en-US">
<html lang={language}>
```
### Fail
```jsx
<html>
```
## Accessibility guidelines
- [WCAG 3.1.1](https://www.w3.org/WAI/WCAG21/Understanding/language-of-page)
### Resources
- [axe-core, html-has-lang](https://dequeuniversity.com/rules/axe/3.2/html-has-lang)
- [axe-core, html-lang-valid](https://dequeuniversity.com/rules/axe/3.2/html-lang-valid)

View file

@ -0,0 +1,33 @@
# iframe-has-title
`<iframe>` elements must have a unique title property to indicate its content to the user.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<iframe title="This is a unique title" />
<iframe title={uniqueTitle} />
```
### Fail
```jsx
<iframe />
<iframe {...props} />
<iframe title="" />
<iframe title={''} />
<iframe title={``} />
<iframe title={undefined} />
<iframe title={false} />
<iframe title={true} />
<iframe title={42} />
```
## Accessibility guidelines
- [WCAG 2.4.1](https://www.w3.org/WAI/WCAG21/Understanding/bypass-blocks)
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [axe-core, frame-title](https://dequeuniversity.com/rules/axe/3.2/frame-title)

View file

@ -0,0 +1,44 @@
# img-redundant-alt
Enforce img alt attribute does not contain the word image, picture, or photo. Screenreaders already announce `img` elements as an image. There is no need to use words such as *image*, *photo*, and/or *picture*.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/img-redundant-alt": [ 2, {
"components": [ "Image" ],
"words": [ "Bild", "Foto" ],
}],
}
}
```
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).
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.
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.
### Succeed
```jsx
<img src="foo" alt="Foo eating a sandwich." />
<img src="bar" aria-hidden alt="Picture of me taking a photo of an image" /> // Will pass because it is hidden.
<img src="baz" alt={`Baz taking a ${photo}`} /> // This is valid since photo is a variable name.
```
### Fail
```jsx
<img src="foo" alt="Photo of foo being weird." />
<img src="bar" alt="Image of me at a bar!" />
<img src="baz" alt="Picture of baz fixing a bug." />
```
## Accessibility guidelines
General best practice (reference resources)
### Resources
- [WebAIM, Alternative Text](https://webaim.org/techniques/alttext/)

View file

@ -0,0 +1,148 @@
# interactive-supports-focus
Elements with an interactive role and interaction handlers (mouse or key press) must be focusable.
## How do I resolve this error?
### Case: I got the error "Elements with the '${role}' interactive role must be tabbable". How can I fix this?
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.
Add the `tabIndex` property to your component. A value of zero indicates that this element can be tabbed to.
```jsx
<div
role="button"
tabIndex={0} />
```
-- or --
Replace the component with one that renders semantic html element like `<button>`, `<a href>` or `<input>` -- whichever fits your purpose.
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_.
### Case: I got the error "Elements with the '${role}' interactive role must be focusable". How can I fix this?
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.
```jsx
<div role="menu">
<div role="menuitem" tabIndex="0">Open</div>
<div role="menuitem" tabIndex="-1">Save</div>
<div role="menuitem" tabIndex="-1">Close</div>
</div>
```
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.
### Case: This element is not a button, link, menuitem, etc. It is catching bubbled events from elements that it contains
If your element is catching bubbled click or key events from descendant elements, then the proper role for this element is `presentation`.
```jsx
<div
onClick={onClickHandler}
role="presentation">
<button>Save</button>
</div>
```
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.
## Rule details
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).
```js
{
'jsx-a11y/interactive-supports-focus': [
'error',
{
tabbable: [
'button',
'checkbox',
'link',
'searchbox',
'spinbutton',
'switch',
'textbox',
],
},
]
}
```
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.
The list of possible values includes:
```js
[
'button',
'checkbox',
'columnheader',
'combobox',
'grid',
'gridcell',
'link',
'listbox',
'menu',
'menubar',
'menuitem',
'menuitemcheckbox',
'menuitemradio',
'option',
'progressbar',
'radio',
'radiogroup',
'row',
'rowheader',
'searchbox',
'slider',
'spinbutton',
'switch',
'tab',
'tablist',
'textbox',
'toolbar',
'tree',
'treegrid',
'treeitem',
'doc-backlink',
'doc-biblioref',
'doc-glossref',
'doc-noteref',
]
```
### Succeed
```jsx
<!-- Good: div with onClick attribute is hidden from screen reader -->
<div aria-hidden onClick={() => void 0} />
<!-- Good: span with onClick attribute is in the tab order -->
<span onClick="doSomething();" tabIndex="0" role="button">Click me!</span>
<!-- Good: span with onClick attribute may be focused programmatically -->
<span onClick="doSomething();" tabIndex="-1" role="menuitem">Click me too!</span>
<!-- Good: anchor element with href is inherently focusable -->
<a href="javascript:void(0);" onClick="doSomething();">Click ALL the things!</a>
<!-- Good: buttons are inherently focusable -->
<button onClick="doSomething();">Click the button :)</button>
```
### Fail
```jsx
<!-- Bad: span with onClick attribute has no tabindex -->
<span onclick="submitForm();" role="button">Submit</span>
<!-- Bad: anchor element without href is not focusable -->
<a onclick="showNextPage();" role="button">Next page</a>
```
## Accessibility guidelines
- [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)
### Resources
- [Chrome Audit Rules, AX_FOCUS_02](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_02)
- [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)
- [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
- [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)

View file

@ -0,0 +1,144 @@
# label-has-associated-control
Enforce that a label tag has a text label and an associated control.
There are two supported ways to associate a label with a control:
- Wrapping a control in a label tag.
- Adding `htmlFor` to a label and assigning it a DOM ID string that indicates an input on the page.
This rule checks that any `label` tag (or an indicated custom component that will output a `label` tag) either (1) wraps an `input` element (or an indicated custom component that will output an `input` tag) or (2) has an `htmlFor` attribute and that the `label` tag has text content.
## How do I resolve this error?
### Case: I just want a text label associated with an input.
The simplest way to achieve an association between a label and an input is to wrap the input in the label.
```jsx
<label>
Surname
<input type="text" />
</label>
```
All modern browsers and assistive technology will associate the label with the control.
### Case: The label is a sibling of the control.
In this case, use `htmlFor` and an ID to associate the controls.
```jsx
<label htmlFor={domId}>Surname</label>
<input type="text" id={domId} />
```
### Case: My label and input components are custom components.
You can configure the rule to be aware of your custom components.
```jsx
<CustomInputLabel label="Surname">
<CustomInput type="text" value={value} />
</CustomInputLabel>
```
And the configuration:
```json
{
"rules": {
"jsx-a11y/label-has-associated-control": [ 2, {
"labelComponents": ["CustomInputLabel"],
"labelAttributes": ["label"],
"controlComponents": ["CustomInput"],
"depth": 3,
}],
}
}
```
### Case: I have two labels for the same input
If the second `label` is in a different part of the HTML, then the second one can only contain `htmlFor` but not nesting. You will probably need eslint override comment on the second label.
```jsx
{/* eslint jsx-a11y/label-has-associated-control: ["error", { assert: "either" } ] */}
<label htmlFor="a">
Username:
</label>
...
<label htmlFor="a">
<input id="a" />
</label>
```
## How to manage IDs of `input`
A common way to think of `id` with libraries like React is, `id`s should be avoided since it must be unique on the page, and components need to be reusable. Hence it is tempted to generate `id` during render-time if `id` is required. *However:*
IDs shouldn't be generated in the browser, so that server and client rendering are deterministic. Render-time uuids aren't just a hack, they're actually broken and should never be used.
To restate, **every ID needs to be deterministic**, on the server and the client, and guaranteed to be unique on the page. EG: For each input, a required ID prop can be passed down from as far up the tree as possible to guarantee uniqueness.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/label-has-associated-control": [ 2, {
"labelComponents": ["CustomLabel"],
"labelAttributes": ["inputLabel"],
"controlComponents": ["CustomInput"],
"assert": "both",
"depth": 3,
}],
}
}
```
`labelComponents` is a list of custom React Component names that should be checked for an associated control.
`labelAttributes` is a list of attributes to check on the label 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.
`controlComponents` is a list of custom React Components names that will output an input element.
`assert` asserts that the label has htmlFor, a nested label, both or either. Available options: `'htmlFor', 'nesting', 'both', 'either'`.
`depth` (default 2, max 25) is an integer that determines how deep within a `JSXElement` label the rule should look for text content or an element with a label to determine if the `label` element will have an accessible label.
### Fail
```jsx
function Foo(props) {
return <label {...props} />
}
```
### Succeed
```jsx
function Foo(props) {
const {
htmlFor,
...otherProps
} = props;
return <label htmlFor={htmlFor} {...otherProps} />
}
```
### Fail
```jsx
<input type="text" />
<label>Surname</label>
```
### Succeed
```jsx
<label>
<input type="text" />
Surname
</label>
```
## Accessibility guidelines
- [WCAG 1.3.1](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships)
- [WCAG 3.3.2](https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions)
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)

View file

@ -0,0 +1,119 @@
# [Deprecated] label-has-for
*This rule was deprecated in v6.1.0. It will no longer be maintained. Please use [`label-has-associated-control`](label-has-associated-control.md) instead.*
Enforce label tags have associated control.
There are two supported ways to associate a label with a control:
- nesting: by wrapping a control in a label tag
- id: by using the prop `htmlFor` as in `htmlFor=[ID of control]`
To fully cover 100% of assistive devices, you're encouraged to validate for both nesting and id.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/label-has-for": [ 2, {
"components": [ "Label" ],
"required": {
"every": [ "nesting", "id" ]
},
"allowChildren": false
}]
}
}
```
For the `components` option, these strings determine which JSX elements (**always including** `<label>`) should be checked for having `htmlFor` prop. This is a good use case when you have a wrapper component that simply renders a `label` element (like in React):
```js
// Label.js
const Label = props => {
const {
htmlFor,
...otherProps
} = props;
return (
<label htmlFor={htmlFor} {...otherProps} />
);
}
...
// CreateAccount.js (for example)
...
return (
<form>
<input id="firstName" type="text" />
<Label htmlFor="firstName">First Name</Label>
</form>
);
```
The `required` option (defaults to `"required": { "every": ["nesting", "id"] }`) determines which checks are activated. You're allowed to pass in one of the following types:
- string: must be one of the acceptable strings (`"nesting"` or `"id"`)
- object, must have one of the following properties:
- some: an array of acceptable strings, will pass if ANY of the requested checks passed
- every: an array of acceptable strings, will pass if ALL of the requested checks passed
The `allowChildren` option (defaults to `false`) determines whether `{children}` content is allowed to be passed into a `label` element. For example, the following pattern, by default, is not allowed:
```js
<label>{children}</label>
```
However, if `allowChildren` is set to `true`, no error will be raised. If you want to pass in `{children}` content without raising an error, because you cannot be sure what `{children}` will render, then set `allowChildren` to `true`.
Note that passing props as spread attribute without `htmlFor` explicitly defined will cause this rule to fail. Explicitly pass down `htmlFor` prop for rule to pass. The prop must have an actual value to pass. Use `Label` component above as a reference. **It is a good thing to explicitly pass props that you expect to be passed for self-documentation.** For example:
#### Bad
```jsx
function Foo(props) {
return <label {...props} />
}
```
#### Good
```jsx
function Foo({ htmlFor, ...props}) {
return <label htmlFor={htmlFor} {...props} />
}
// OR
function Foo(props) {
const {
htmlFor,
...otherProps
} = props;
return <label htmlFor={htmlFor} {...otherProps} />
}
```
### Succeed
```jsx
<label htmlFor="firstName">
<input type="text" id="firstName" />
First Name
</label>
```
### Fail
```jsx
<input type="text" id="firstName" />
<label>First Name</label>
```
## Accessibility guidelines
- [WCAG 1.3.1](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships)
- [WCAG 3.3.2](https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions)
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)

View file

@ -0,0 +1,29 @@
# lang
The `lang` prop on the `<html>` element must be a valid IETF's BCP 47 language tag.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<html lang="en">
<html lang="en-US">
```
### Fail
```jsx
<html>
<html lang="foo">
```
## Accessibility guidelines
- [WCAG 3.1.1](https://www.w3.org/WAI/WCAG21/Understanding/language-of-page)
### Resources
- [axe-core, valid-lang](https://dequeuniversity.com/rules/axe/3.2/valid-lang)
- [Language tags in HTML and XML](https://www.w3.org/International/articles/language-tags/)
- [IANA Language Subtag Registry](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry)

View file

@ -0,0 +1,44 @@
# media-has-caption
Providing captions for media is essential for deaf users to follow along. Captions should be a transcription or translation of the dialogue, sound effects, relevant musical cues, and other relevant audio information. Not only is this important for accessibility, but can also be useful for all users in the case that the media is unavailable (similar to `alt` text on an image when an image is unable to load).
The captions should contain all important and relevant information to understand the corresponding media. This may mean that the captions are not a 1:1 mapping of the dialogue in the media content. However, captions are *not* necessary for video components with the `muted` attribute.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/media-has-caption": [ 2, {
"audio": [ "Audio" ],
"video": [ "Video" ],
"track": [ "Track" ],
}],
}
}
```
For the `audio`, `video`, and `track` options, these strings determine which JSX elements (**always including** their corresponding DOM element) should be used for this rule. This is a good use case when you have a wrapper component that simply renders an `audio`, `video`, or `track` element (like in React):
### Succeed
```jsx
<audio><track kind="captions" {...props} /></audio>
<video><track kind="captions" {...props} /></video>
<video muted {...props} ></video>
```
### Fail
```jsx
<audio {...props} />
<video {...props} />
```
## Accessibility guidelines
- [WCAG 1.2.2](https://www.w3.org/WAI/WCAG21/Understanding/captions-prerecorded.html)
- [WCAG 1.2.3](https://www.w3.org/WAI/WCAG21/Understanding/audio-description-or-media-alternative-prerecorded.html)
### Resources
- [axe-core, audio-caption](https://dequeuniversity.com/rules/axe/2.1/audio-caption)
- [axe-core, video-caption](https://dequeuniversity.com/rules/axe/2.1/video-caption)

View file

@ -0,0 +1,28 @@
# mouse-events-have-key-events
Enforce onmouseover/onmouseout are accompanied by onfocus/onblur. Coding for the keyboard is important for users with physical disabilities who cannot use a mouse, AT compatibility, and screenreader users.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<div onMouseOver={ () => void 0 } onFocus={ () => void 0 } />
<div onMouseOut={ () => void 0 } onBlur={ () => void 0 } />
<div onMouseOver={ () => void 0 } onFocus={ () => void 0 } {...otherProps} />
<div onMouseOut={ () => void 0 } onBlur={ () => void 0 } {...otherProps} />
```
### Fail
In example 3 and 4 below, even if otherProps contains onBlur and/or onFocus, this rule will still fail. Props should be passed down explicitly for rule to pass.
```jsx
<div onMouseOver={ () => void 0 } />
<div onMouseOut={ () => void 0 } />
<div onMouseOver={ () => void 0 } {...otherProps} />
<div onMouseOut={ () => void 0 } {...otherProps} />
```
## Accessibility guidelines
- [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)

View file

@ -0,0 +1,26 @@
# no-access-key
Enforce no accessKey prop on element. Access keys are HTML attributes that allow web developers to assign keyboard shortcuts to elements. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreader and keyboard only users create accessibility complications so to avoid complications, access keys should not be used.
### References
1. [WebAIM](http://webaim.org/techniques/keyboard/accesskey#spec)
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<div />
```
### Fail
```jsx
<div accessKey="h" />
```
## Accessibility guidelines
General best practice (reference resources)
### Resources
- [WebAIM, Keyboard Accessibility: Accesskey](http://webaim.org/techniques/keyboard/accesskey#spec)

View file

@ -0,0 +1,39 @@
# no-autofocus
Enforce that autoFocus prop is not used on elements. Autofocusing elements can cause usability issues for sighted and non-sighted users, alike.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/no-autofocus": [ 2, {
"ignoreNonDOM": true
}],
}
}
```
For the `ignoreNonDOM` option, this determines if developer created components are checked.
### Succeed
```jsx
<div />
```
### Fail
```jsx
<div autoFocus />
<div autoFocus="true" />
<div autoFocus="false" />
<div autoFocus={undefined} />
```
## Accessibility guidelines
General best practice (reference resources)
### Resources
- [WHATWG HTML Standard, The autofocus attribute](https://html.spec.whatwg.org/multipage/interaction.html#attr-fe-autofocus)
- [The accessibility of HTML 5 autofocus](https://www.brucelawson.co.uk/2009/the-accessibility-of-html-5-autofocus/)

View file

@ -0,0 +1,37 @@
# no-distracting-elements
Enforces that no distracting elements are used. Elements that can be visually distracting can cause accessibility issues with visually impaired users. Such elements are most likely deprecated, and should be avoided. By default, the following elements are visually distracting: `<marquee>` and `<blink>`.
## Rule details
This rule takes one optional object argument of type object:
```json
{
"rules": {
"jsx-a11y/no-distracting-elements": [ 2, {
"elements": [ "marquee", "blink" ],
}],
}
}
```
For the `elements` option, these strings determine which JSX elements should be checked for usage. This shouldn't need to be configured unless you have a seriously compelling use case for these elements. You cannot add any additional elements than what is offered, as the schema is only valid with the provided enumerated list. If you have another element that you think may cause a11y issues due to visual impairment, please feel free to file an issue or send a PR!
### Succeed
```jsx
<div />
```
### Fail
```jsx
<marquee />
<blink />
```
## Accessibility guidelines
- [WCAG 2.2.2](https://www.w3.org/WAI/WCAG21/Understanding/pause-stop-hide)
### Resources
- [axe-core, marquee](https://dequeuniversity.com/rules/axe/3.2/marquee)
- [axe-core, blink](https://dequeuniversity.com/rules/axe/3.2/blink)

View file

@ -0,0 +1,67 @@
# no-interactive-element-to-noninteractive-role
Interactive HTML elements indicate _controls_ in the user interface. Interactive elements include `<a href>`, `<button>`, `<input>`, `<select>`, `<textarea>`.
Non-interactive HTML elements and non-interactive ARIA roles indicate _content_ and _containers_ in the user interface. Non-interactive elements include `<main>`, `<area>`, `<h1>` (,`<h2>`, etc), `<img>`, `<li>`, `<ul>` and `<ol>`.
[WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) should not be used to convert an interactive element to a non-interactive element. Non-interactive ARIA roles include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
## How do I resolve this error?
### Case: The element should be a container, like an article
Wrap your interactive element in a `<div>` with the desired role.
```jsx
<div role="article">
<button>Save</button>
</div>
```
### Case: The element should be content, like an image
Put the content inside your interactive element.
```jsx
<div
role="button"
onClick={() => {}}
onKeyPress={() => {}}
tabIndex="0">
<div role="img" aria-label="Save" />
</div>
```
## Rule details
The recommended options for this rule allow the `tr` element to be given a role of `presentation` (or its semantic equivalent `none`). Under normal circumstances, an element with an interactive role should not be semantically neutralized with `presentation` (or `none`).
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.
```js
{
'no-interactive-element-to-noninteractive-role': [
'error',
{
tr: ['none', 'presentation'],
},
]
}
```
Under the recommended options, the following code is valid. It would be invalid under the strict rules.
```jsx
<tr role="presentation" />
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [ARIA Spec, States and Properties](https://www.w3.org/TR/wai-aria/#states_and_properties)
- [Chrome Audit Rules, AX_ARIA_04](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_04)
- [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)
- [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)
- [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
- [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)

View file

@ -0,0 +1,137 @@
# no-noninteractive-element-interactions
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`.
## How do I resolve this error?
### Case: This element acts like a button, link, menuitem, etc.
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.
Common interactive roles include:
1. `button`
1. `link`
1. `checkbox`
1. `menuitem`
1. `menuitemcheckbox`
1. `menuitemradio`
1. `option`
1. `radio`
1. `searchbox`
1. `switch`
1. `textbox`
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.
see [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex).
### Case: This element is catching bubbled events from elements that it contains
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.
```jsx
<div role="article">
<div
onClick="onClickHandler"
onKeyPress={onKeyPressHandler}
role="presentation">
{this.props.children}
</div>
</div>
```
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.
### Case: This is a heading that expands/collapses content on the package
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.
```jsx
<h3>
<button onClick={this._expandSection}>News</button>
</h3>
<ul id="articles-list">
<li>...</li>
</ul>
```
### Case: This element is a table cell
Table cells (and tables in general) are meant to contain data. ARIA provides us with a construct called a [Grid](http://w3c.github.io/aria-practices/#grid) that is essentially a 2 dimensional logical container for content and interactive elements.
You have two options in this case.
#### Option 1, move the interactive content inside the table cells
For instance, move the button inside the cell:
```jsx
<table>
<tr>
<td><button>Sort</button></td>
</tr>
</table>
```
This preserves the table cell semantics and the button semantics; the two are not conflated on the cell.
#### Option 2, convert the table into an ARIA grid
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.
```jsx
<table role="grid">
<tr>
<td role="gridcell" onClick={this.sort}>Sort</td>
</tr>
</table>
```
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.
## Rule details
You may configure which handler props should be taken into account when applying this rule. The recommended configuration includes the following 6 handlers.
```javascript
'jsx-a11y/no-noninteractive-element-interactions': [
'error',
{
handlers: [
'onClick',
'onMouseDown',
'onMouseUp',
'onKeyPress',
'onKeyDown',
'onKeyUp',
],
},
],
```
Adjust the list of handler prop names in the handlers array to increase or decrease the coverage surface of this rule in your codebase.
### Succeed
```jsx
<div onClick={() => void 0} role="button" />
<div onClick={() => void 0} role="presentation" />
<input type="text" onClick={() => void 0} /> // Interactive element does not require role.
<button onClick={() => void 0} className="foo" /> // button is interactive.
<div onClick={() => void 0} role="button" aria-hidden /> // This is hidden from screenreader.
<Input onClick={() => void 0} type="hidden" /> // This is a higher-level DOM component
```
### Fail
```jsx
<li onClick={() => void 0} />
<div onClick={() => void 0} role="listitem" />
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)
- [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)
- [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
- [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)

View file

@ -0,0 +1,71 @@
# no-noninteractive-element-to-interactive-role
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>`.
Interactive HTML elements indicate _controls_ in the user interface. Interactive elements include `<a href>`, `<button>`, `<input>`, `<select>`, `<textarea>`.
[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`.
## How do I resolve this error?
### Case: This element should be a control, like a button
Put the control inside the non-interactive container element.
```jsx
<li>
<div
role="button"
onClick={() => {}}
onKeyPress={() => {}}>
Save
</div>
</li>
```
Or wrap the content inside your interactive element.
```jsx
<div
role="button"
onClick={() => {}}
onKeyPress={() => {}}
tabIndex="0">
<img src="some/file.png" alt="Save" />
</div>
```
## Rule details
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.
```js
{
'no-noninteractive-element-to-interactive-role': [
'error',
{
ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
table: ['grid'],
td: ['gridcell'],
},
]
}
```
Under the recommended options, the following code is valid. It would be invalid under the strict rules.
```jsx
<ul role="menu" />
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)
- [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)
- [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
- [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)

View file

@ -0,0 +1,89 @@
# no-noninteractive-tabindex
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.
## How do I resolve this error?
### Case: I am using an `<a>` tag. Isn't that interactive?
The `<a>` tag is tricky. Consider the following:
```jsx
<a>Edit</a>
<a href="#">Edit</a>
<a role="button">Edit</a>
```
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`.
### Case: I am using "semantic" HTML. Isn't that interactive?
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?
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>`.
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.
Common interactive roles include:
1. `button`
1. `link`
1. `checkbox`
1. `menuitem`
1. `menuitemcheckbox`
1. `menuitemradio`
1. `option`
1. `radio`
1. `searchbox`
1. `switch`
1. `textbox`
Endeavor to limit tabbable elements to those that a user can act upon.
### Case: Shouldn't I add a tabindex so that users can navigate to this item?
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.
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.
## Rule details
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.
```javascript
'jsx-a11y/no-noninteractive-tabindex': [
'error',
{
tags: [],
roles: ['tabpanel'],
},
]
```
### Succeed
```jsx
<div />
<MyButton tabIndex={0} />
<button />
<button tabIndex="0" />
<button tabIndex={0} />
<div />
<div tabIndex="-1" />
<div role="button" tabIndex="0" />
<div role="article" tabIndex="-1" />
<article tabIndex="-1" />
```
### Fail
```jsx
<div tabIndex="0" />
<div role="article" tabIndex="0" />
<article tabIndex="0" />
<article tabIndex={0} />
```
## Accessibility guidelines
- [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard)
### Resources
- [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)

View file

@ -0,0 +1,30 @@
# no-onchange
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.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<select onBlur={updateModel}>
<option/>
</select>
<select>
<option onBlur={handleOnBlur} onChange={handleOnChange} />
</select>
```
### Fail
```jsx
<select onChange={updateModel} />
```
## Accessibility guidelines
- [WCAG 3.2.2](https://www.w3.org/WAI/WCAG21/Understanding/on-input)
### Resources
- [onChange Event Accessibility Issues](http://cita.disability.uiuc.edu/html-best-practices/auto/onchange.php)
- [onChange Select Menu](http://www.themaninblue.com/writing/perspective/2004/10/19/)

View file

@ -0,0 +1,36 @@
# no-redundant-roles
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.
## Rule details
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.
```js
{
'jsx-a11y/no-redundant-roles': [
'error',
{
nav: ['navigation'],
},
}
```
### Succeed
```jsx
<div />
<button role="presentation" />
<MyComponent role="main" />
```
### Fail
```jsx
<button role="button" />
<img role="img" src="foo.jpg" />
```
## Accessibility guidelines
General best practice (reference resources)
### Resources
- [ARIA Spec, ARIA Adds Nothing to Default Semantics of Most HTML Elements](https://www.w3.org/TR/using-aria/#aria-does-nothing)

View file

@ -0,0 +1,99 @@
# no-static-element-interactions
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>`.
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.
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.
## How do I resolve this error?
### Case: This element acts like a button, link, menuitem, etc.
Indicate the element's role with the `role` attribute:
```jsx
<div
onClick={onClickHandler}
onKeyPress={onKeyPressHandler}
role="button"
tabIndex="0">
Save
</div>
```
Common interactive roles include:
1. `button`
1. `link`
1. `checkbox`
1. `menuitem`
1. `menuitemcheckbox`
1. `menuitemradio`
1. `option`
1. `radio`
1. `searchbox`
1. `switch`
1. `textbox`
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.
### Case: The event handler is only being used to capture bubbled events
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.
```jsx
{/* The <div> element has a child <button> element that allows keyboard interaction */}
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
<div onClick={this.handleButtonClick}>
<button>Save</button>
<button>Cancel</button>
</div>
```
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.
## Rule details
You may configure which handler props should be taken into account when applying this rule. The recommended configuration includes the following 6 handlers.
```javascript
'jsx-a11y/no-static-element-interactions': [
'error',
{
handlers: [
'onClick',
'onMouseDown',
'onMouseUp',
'onKeyPress',
'onKeyDown',
'onKeyUp',
],
},
],
```
Adjust the list of handler prop names in the handlers array to increase or decrease the coverage surface of this rule in your codebase.
### Succeed
```jsx
<button onClick={() => {}} className="foo" />
<div className="foo" onClick={() => {}} role="button" />
<input type="text" onClick={() => {}} />
```
### Fail
```jsx
<div onClick={() => {}} />
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [WAI-ARIA `role` attribute](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)
- [WAI-ARIA Authoring Practices Guide - Design Patterns and Widgets](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_ex)
- [Fundamental Keyboard Navigation Conventions](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_generalnav)
- [Mozilla Developer Network - ARIA Techniques](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Keyboard_and_focus)

View file

@ -0,0 +1,27 @@
# role-has-required-aria-props
Elements with ARIA roles must have all required attributes for that role.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<!-- Good: the checkbox role requires the aria-checked state -->
<span role="checkbox" aria-checked="false" aria-labelledby="foo" tabindex="0"></span>
```
### Fail
```jsx
<!-- Bad: the checkbox role requires the aria-checked state -->
<span role="checkbox" aria-labelledby="foo" tabindex="0"></span>
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [ARIA Spec, Roles](https://www.w3.org/TR/wai-aria/#roles)
- [Chrome Audit Rules, AX_ARIA_03](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_03)

View file

@ -0,0 +1,35 @@
# role-supports-aria-props
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"`.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<!-- Good: the radiogroup role does support the aria-required property -->
<ul role="radiogroup" aria-required aria-labelledby="foo">
<li tabIndex="-1" role="radio" aria-checked="false">Rainbow Trout</li>
<li tabIndex="-1" role="radio" aria-checked="false">Brook Trout</li>
<li tabIndex="0" role="radio" aria-checked="true">Lake Trout</li>
</ul>
```
### Fail
```jsx
<!-- Bad: the radio role does not support the aria-required property -->
<ul role="radiogroup" aria-labelledby="foo">
<li aria-required tabIndex="-1" role="radio" aria-checked="false">Rainbow Trout</li>
<li aria-required tabIndex="-1" role="radio" aria-checked="false">Brook Trout</li>
<li aria-required tabIndex="0" role="radio" aria-checked="true">Lake Trout</li>
</ul>
```
## Accessibility guidelines
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)
### Resources
- [ARIA Spec, States and Properties](https://www.w3.org/TR/wai-aria/#states_and_properties)
- [Chrome Audit Rules, AX_ARIA_10](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_10)

View file

@ -0,0 +1,26 @@
# scope
The `scope` scope should be used only on `<th>` elements.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<th scope="col" />
<th scope={scope} />
```
### Fail
```jsx
<div scope />
```
## Accessibility guidelines
- [WCAG 1.3.1](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships)
- [WCAG 4.1.1](https://www.w3.org/WAI/WCAG21/Understanding/parsing)
### Resources
- [axe-core, scope-attr-valid](https://dequeuniversity.com/rules/axe/3.5/scope-attr-valid)

View file

@ -0,0 +1,28 @@
# tabindex-no-positive
Avoid positive `tabIndex` property values to synchronize the flow of the page with keyboard tab order.
## Rule details
This rule takes no arguments.
### Succeed
```jsx
<span tabIndex="0">foo</span>
<span tabIndex="-1">bar</span>
<span tabIndex={0}>baz</span>
```
### Fail
```jsx
<span tabIndex="5">foo</span>
<span tabIndex="3">bar</span>
<span tabIndex="1">baz</span>
<span tabIndex="2">never really sure what goes after baz</span>
```
## Accessibility guidelines
- [WCAG 2.4.3](https://www.w3.org/WAI/WCAG21/Understanding/focus-order)
### Resources
- [Chrome Audit Rules, AX_FOCUS_03](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_03)