Skip to content

Commit 2840c3a

Browse files
authored
Merge branch 'main' into kh-rename-files
2 parents 57dfee5 + 8d691db commit 2840c3a

17 files changed

+687
-264
lines changed

README.md

+29-27
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,16 @@ _Note: This is experimental and subject to change._
4747

4848
The `react` config includes rules which target specific HTML elements. You may provide a mapping of custom components to an HTML element in your `eslintrc` configuration to increase linter coverage.
4949

50-
For each component, you may specify a `default` and/or `props`. `default` may make sense if there's a 1:1 mapping between a component and an HTML element. However, if the HTML output of a component is dependent on a prop value, you can provide a mapping using the `props` key. To minimize conflicts and complexity, this currently only supports the mapping of a single prop type.
50+
By default, these eslint rules will check the "as" prop for underlying element changes. If your repo uses a different prop name for polymorphic components provide the prop name in your `eslintrc` configuration under `polymorphicPropName`.
5151

5252
```json
5353
{
5454
"settings": {
5555
"github": {
56+
"polymorphicPropName": "asChild",
5657
"components": {
57-
"Box": {"default": "p"},
58-
"Link": {"props": {"as": {"undefined": "a", "a": "a", "button": "button"}}}
58+
"Box": "p",
59+
"Link": "a"
5960
}
6061
}
6162
}
@@ -66,9 +67,7 @@ This config will be interpreted in the following way:
6667

6768
- All `<Box>` elements will be treated as a `p` element type.
6869
- `<Link>` without a defined `as` prop will be treated as a `a`.
69-
- `<Link as='a'>` will treated as an `a` element type.
7070
- `<Link as='button'>` will be treated as a `button` element type.
71-
- `<Link as='summary'>` will be treated as the raw `Link` type because there is no configuration set for `as='summary'`.
7271

7372
### Rules
7473

@@ -82,28 +81,31 @@ This config will be interpreted in the following way:
8281
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
8382
❌ Deprecated.
8483

85-
| Name                              | Description | 💼 | 🔧 ||
86-
| :----------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :- | :- | :- |
87-
| [a11y-aria-label-is-well-formatted](docs/rules/a11y-aria-label-is-well-formatted.md) | [aria-label] text should be formatted as you would visual text. | ⚛️ | | |
88-
| [a11y-no-generic-link-text](docs/rules/a11y-no-generic-link-text.md) | disallow generic link text | | ||
84+
| Name                                        | Description | 💼 | 🔧 ||
85+
| :------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :- | :- | :- |
86+
| [a11y-aria-label-is-well-formatted](docs/rules/a11y-aria-label-is-well-formatted.md) | [aria-label] text should be formatted as you would visual text. | ⚛️ | | |
87+
| [a11y-no-generic-link-text](docs/rules/a11y-no-generic-link-text.md) | disallow generic link text | | ||
88+
| [a11y-no-title-attribute](docs/rules/a11y-no-title-attribute.md) | Guards against developers using the title attribute | ⚛️ | | |
89+
| [a11y-no-visually-hidden-interactive-element](docs/rules/a11y-no-visually-hidden-interactive-element.md) | Ensures that interactive elements are not visually hidden | ⚛️ | | |
8990
| [a11y-role-supports-aria-props](docs/rules/a11y-role-supports-aria-props.md) | Enforce that elements with explicit or implicit roles defined contain only `aria-*` properties supported by that `role`. | ⚛️ | | |
90-
| [array-foreach](docs/rules/array-foreach.md) | enforce `for..of` loops over `Array.forEach` || | |
91-
| [async-currenttarget](docs/rules/async-currenttarget.md) | disallow `event.currentTarget` calls inside of async functions | 🔍 | | |
92-
| [async-preventdefault](docs/rules/async-preventdefault.md) | disallow `event.preventDefault` calls inside of async functions | 🔍 | | |
93-
| [authenticity-token](docs/rules/authenticity-token.md) | disallow usage of CSRF tokens in JavaScript | 🔐 | | |
94-
| [get-attribute](docs/rules/get-attribute.md) | disallow wrong usage of attribute names | 🔍 | 🔧 | |
95-
| [js-class-name](docs/rules/js-class-name.md) | enforce a naming convention for js- prefixed classes | 🔐 | | |
96-
| [no-blur](docs/rules/no-blur.md) | disallow usage of `Element.prototype.blur()` | 🔍 | | |
97-
| [no-d-none](docs/rules/no-d-none.md) | disallow usage the `d-none` CSS class | 🔐 | | |
98-
| [no-dataset](docs/rules/no-dataset.md) | enforce usage of `Element.prototype.getAttribute` instead of `Element.prototype.datalist` | 🔍 | | |
99-
| [no-dynamic-script-tag](docs/rules/no-dynamic-script-tag.md) | disallow creating dynamic script tags || | |
100-
| [no-implicit-buggy-globals](docs/rules/no-implicit-buggy-globals.md) | disallow implicit global variables || | |
101-
| [no-inner-html](docs/rules/no-inner-html.md) | disallow `Element.prototype.innerHTML` in favor of `Element.prototype.textContent` | 🔍 | | |
102-
| [no-innerText](docs/rules/no-innerText.md) | disallow `Element.prototype.innerText` in favor of `Element.prototype.textContent` | 🔍 | 🔧 | |
103-
| [no-then](docs/rules/no-then.md) | enforce using `async/await` syntax over Promises || | |
104-
| [no-useless-passive](docs/rules/no-useless-passive.md) | disallow marking a event handler as passive when it has no effect | 🔍 | 🔧 | |
105-
| [prefer-observers](docs/rules/prefer-observers.md) | disallow poorly performing event listeners | 🔍 | | |
106-
| [require-passive-events](docs/rules/require-passive-events.md) | enforce marking high frequency event handlers as passive | 🔍 | | |
107-
| [unescaped-html-literal](docs/rules/unescaped-html-literal.md) | disallow unescaped HTML literals | 🔍 | | |
91+
| [a11y-svg-has-accessible-name](docs/rules/a11y-svg-has-accessible-name.md) | SVGs must have an accessible name | ⚛️ | | |
92+
| [array-foreach](docs/rules/array-foreach.md) | enforce `for..of` loops over `Array.forEach` || | |
93+
| [async-currenttarget](docs/rules/async-currenttarget.md) | disallow `event.currentTarget` calls inside of async functions | 🔍 | | |
94+
| [async-preventdefault](docs/rules/async-preventdefault.md) | disallow `event.preventDefault` calls inside of async functions | 🔍 | | |
95+
| [authenticity-token](docs/rules/authenticity-token.md) | disallow usage of CSRF tokens in JavaScript | 🔐 | | |
96+
| [get-attribute](docs/rules/get-attribute.md) | disallow wrong usage of attribute names | 🔍 | 🔧 | |
97+
| [js-class-name](docs/rules/js-class-name.md) | enforce a naming convention for js- prefixed classes | 🔐 | | |
98+
| [no-blur](docs/rules/no-blur.md) | disallow usage of `Element.prototype.blur()` | 🔍 | | |
99+
| [no-d-none](docs/rules/no-d-none.md) | disallow usage the `d-none` CSS class | 🔐 | | |
100+
| [no-dataset](docs/rules/no-dataset.md) | enforce usage of `Element.prototype.getAttribute` instead of `Element.prototype.datalist` | 🔍 | | |
101+
| [no-dynamic-script-tag](docs/rules/no-dynamic-script-tag.md) | disallow creating dynamic script tags || | |
102+
| [no-implicit-buggy-globals](docs/rules/no-implicit-buggy-globals.md) | disallow implicit global variables || | |
103+
| [no-inner-html](docs/rules/no-inner-html.md) | disallow `Element.prototype.innerHTML` in favor of `Element.prototype.textContent` | 🔍 | | |
104+
| [no-innerText](docs/rules/no-innerText.md) | disallow `Element.prototype.innerText` in favor of `Element.prototype.textContent` | 🔍 | 🔧 | |
105+
| [no-then](docs/rules/no-then.md) | enforce using `async/await` syntax over Promises || | |
106+
| [no-useless-passive](docs/rules/no-useless-passive.md) | disallow marking a event handler as passive when it has no effect | 🔍 | 🔧 | |
107+
| [prefer-observers](docs/rules/prefer-observers.md) | disallow poorly performing event listeners | 🔍 | | |
108+
| [require-passive-events](docs/rules/require-passive-events.md) | enforce marking high frequency event handlers as passive | 🔍 | | |
109+
| [unescaped-html-literal](docs/rules/unescaped-html-literal.md) | disallow unescaped HTML literals | 🔍 | | |
108110

109111
<!-- end auto-generated rules list -->

docs/rules/a11y-no-title-attribute.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Guards against developers using the title attribute (`github/a11y-no-title-attribute`)
2+
3+
💼 This rule is enabled in the ⚛️ `react` config.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
The title attribute is strongly discouraged. The only exception is on an `<iframe>` element. It is hardly useful and cannot be accessed by multiple groups of users including keyboard-only users and mobile users.
8+
9+
The `title` attribute is commonly set on links, matching the link text. This is redundant and unnecessary so it can be simply be removed.
10+
11+
If you are considering the `title` attribute to provide supplementary description, consider whether the text in question can be persisted in the design. Alternatively, if it's important to display supplementary text that is hidden by default, consider using an accessible tooltip implementation that uses the aria-labelledby or aria-describedby semantics. Even so, proceed with caution: tooltips should only be used on interactive elements like links or buttons. See [Tooltip alternatives](https://primer.style/design/guides/accessibility/tooltip-alternatives) for more accessible alternatives.
12+
13+
### Should I use the title attribute to provide an accessible name for an <svg>?
14+
15+
Use a <title> element instead of the title attribute, or an aria-label.
16+
17+
## Rule Details
18+
19+
👎 Examples of **incorrect** code for this rule:
20+
21+
```jsx
22+
<a src="https://www.github.com" title="A home for all developers">
23+
GitHub
24+
</a>
25+
```
26+
27+
```jsx
28+
<a href="/" title="github.com">
29+
GitHub
30+
</a>
31+
```
32+
33+
```jsx
34+
<span src="https://www.github.com" title="supercalifragilisticexpialidocious">
35+
supercali...
36+
</span>
37+
```
38+
39+
👍 Examples of **correct** code for this rule:
40+
41+
```jsx
42+
<iframe src="https://www.github.com" title="Github"></iframe>
43+
```
44+
45+
## Version
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Ensures that interactive elements are not visually hidden (`github/a11y-no-visually-hidden-interactive-element`)
2+
3+
💼 This rule is enabled in the ⚛️ `react` config.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
## Rule Details
8+
9+
This rule guards against visually hiding interactive elements. If a sighted keyboard user navigates to an interactive element that is visually hidden they might become confused and assume that keyboard focus has been lost.
10+
11+
Note: we are not guarding against visually hidden `input` elements at this time. Some visually hidden inputs might cause a false positive (e.g. some file inputs).
12+
13+
### Why do we visually hide content?
14+
15+
Visually hiding content can be useful when you want to provide information specifically to screen reader users or other assitive technology users while keeping content hidden from sighted users.
16+
17+
Applying the following css will visually hide content while still making it accessible to screen reader users.
18+
19+
```css
20+
clip-path: inset(50%);
21+
height: 1px;
22+
overflow: hidden;
23+
position: absolute;
24+
white-space: nowrap;
25+
width: 1px;
26+
```
27+
28+
👎 Examples of **incorrect** code for this rule:
29+
30+
```jsx
31+
<button className="visually-hidden">Submit</button>
32+
```
33+
34+
```jsx
35+
<VisuallyHidden>
36+
<button>Submit</button>
37+
</VisuallyHidden>
38+
```
39+
40+
```jsx
41+
<VisuallyHidden as="button">Submit</VisuallyHidden>
42+
```
43+
44+
👍 Examples of **correct** code for this rule:
45+
46+
```jsx
47+
<h2 className="visually-hidden">Welcome to GitHub</h2>
48+
```
49+
50+
```jsx
51+
<VisuallyHidden>
52+
<h2>Welcome to GitHub</h2>
53+
</VisuallyHidden>
54+
```
55+
56+
```jsx
57+
<VisuallyHidden as="h2">Welcome to GitHub</VisuallyHidden>
58+
```
59+
60+
## Options
61+
62+
- className - A css className that visually hides content. Defaults to `sr-only`.
63+
- componentName - A react component name that visually hides content. Defaults to `VisuallyHidden`.
64+
- htmlPropName - A prop name used to replace the semantic element that is rendered. Defaults to `as`.
65+
66+
```json
67+
{
68+
"a11y-no-visually-hidden-interactive-element": [
69+
"error",
70+
{
71+
"className": "visually-hidden",
72+
"componentName": "VisuallyHidden",
73+
"htmlPropName": "as"
74+
}
75+
]
76+
}
77+
```
78+
79+
## Version
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# SVGs must have an accessible name (`github/a11y-svg-has-accessible-name`)
2+
3+
💼 This rule is enabled in the ⚛️ `react` config.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
## Rule Details
8+
9+
An `<svg>` must have an accessible name. Set `aria-label` or `aria-labelledby`, or nest a `<title>` element as the first child of the `<svg>` element.
10+
11+
However, if the `<svg>` is purely decorative, hide it with `aria-hidden="true"` or `role="presentation"`.
12+
13+
## Resources
14+
15+
- [Accessible SVGs](https://css-tricks.com/accessible-svgs/)
16+
17+
## Examples
18+
19+
### **Incorrect** code for this rule 👎
20+
21+
```html
22+
<svg height='100' width='100'>
23+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
24+
</svg>
25+
```
26+
27+
```html
28+
<svg height='100' width='100' title='Circle with a black outline and red fill'>
29+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
30+
</svg>
31+
```
32+
33+
```html
34+
<svg height='100' width='100'>
35+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
36+
<title>Circle with a black outline and red fill</title>
37+
</svg>
38+
```
39+
40+
### **Correct** code for this rule 👍
41+
42+
```html
43+
<svg height='100' width='100'>
44+
<title>Circle with a black outline and red fill</title>
45+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
46+
</svg>
47+
```
48+
49+
```html
50+
<svg aria-label='Circle with a black outline and red fill' height='100' width='100'>
51+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
52+
</svg>
53+
```
54+
55+
```html
56+
<svg aria-labelledby='circle_text' height='100' width='100'>
57+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
58+
</svg>
59+
```
60+
61+
```html
62+
<svg aria-hidden='true' height='100' width='100'>
63+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
64+
</svg>
65+
```
66+
67+
```html
68+
<svg role='presentation' height='100' width='100'>
69+
<circle cx='50' cy='50' r='40' stroke='black' stroke-width='3' fill='red'/>
70+
</svg>
71+
```
72+
73+
## Version

0 commit comments

Comments
 (0)