Skip to content

Commit 05a3cab

Browse files
committed
Refactored code into seprate files and utility file
1 parent 7e6d8e4 commit 05a3cab

10 files changed

+279
-132
lines changed
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# no-aria-hidden-on-focusbable
2+
3+
Enforce that `aria-hidden="true"` is not set on focusable elements or parent of focusable elements.
4+
5+
`aria-hidden="true"` can be used to hide purely decorative content from screen reader users. An element with `aria-hidden="true"` that can also be reached by keyboard can lead to confusion or unexpected behavior for screen reader users. Avoid using `aria-hidden="true"` on focusable elements.
6+
7+
See more in [WAI-ARIA Use in HTML](https://www.w3.org/TR/using-aria/#fourth).
8+
9+
10+
### ✔ Succeed
11+
```vue
12+
<template>
13+
<button>Press Me</button>
14+
</template>
15+
```
16+
17+
```vue
18+
<template>
19+
<div aria-hidden='true'><button tabindex='-1'>Submit</button></div>
20+
</template>
21+
```
22+
23+
24+
```vue
25+
<template>
26+
<div aria-hidden='true'><span>Some text</div></div>
27+
</template>
28+
```
29+
30+
```vue
31+
<template>
32+
<button tabindex='-1' aria-hidden='true'>Press</button>
33+
</template>
34+
```
35+
36+
```vue
37+
<template>
38+
<div aria-hidden='true'><a href='#' tabindex='-1'>Link</a></div>
39+
</template>
40+
```
41+
42+
```vue
43+
<template>
44+
<div aria-hidden='true'><span>Some text</div></div>
45+
</template>
46+
```
47+
48+
### ❌ Fail
49+
50+
```vue
51+
<template>
52+
<button aria-hidden='true'>press me</button>
53+
</template>
54+
```
55+
56+
```vue
57+
<template>
58+
<button aria-hidden="true">press me</button>
59+
</template>
60+
```
61+
```vue
62+
<template>
63+
<a href="#" aria-hidden='true'>press me</a>
64+
</template>
65+
```
66+
```vue
67+
<template>
68+
<div aria-hidden="true">
69+
<button>press me</button>
70+
</div>
71+
</template>
72+
```
73+
```vue
74+
<template>
75+
<span tabindex='0' aria-hidden='true'><em>Icon</em></span>
76+
</template>
77+
```

docs/rules/no-presentation-role-or-aria-hidden-on-focusable.md

-68
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# no-role-presentaion-on-focusbable
2+
3+
Enforce that `role="presentation"` is not set on focusable elements or parent of focusbale elements.
4+
5+
`role="presentation` can be used to hide purely decorative content from screen reader users. An element with `role="presentation"` that can also be reached by keyboard can lead to confusion or unexpected behavior for screen reader users. Avoid using `role="presentation"` on focusable elements.
6+
7+
See more in [WAI-ARIA Use in HTML](https://www.w3.org/TR/using-aria/#fourth).
8+
9+
10+
### ✔ Succeed
11+
```vue
12+
<template>
13+
<button>Press Me</button>
14+
</template>
15+
```
16+
17+
```vue
18+
<template>
19+
<div role="presentation"><button tabindex='-1'>Submit</button></div>
20+
</template>
21+
```
22+
23+
24+
```vue
25+
<template>
26+
<div role="presentation"><span>Some text</div></div>
27+
</template>
28+
```
29+
30+
```vue
31+
<template>
32+
<button tabindex='-1' role="presentation">Press</button>
33+
</template>
34+
```
35+
36+
```vue
37+
<template>
38+
<div role="presentation"><a href='#' tabindex='-1'>Link</a></div>
39+
</template>
40+
```
41+
42+
```vue
43+
<template>
44+
<div role="presentation"><span>Some text</div></div>
45+
</template>
46+
```
47+
48+
### ❌ Fail
49+
50+
```vue
51+
<template>
52+
<button role="presentation">press me</button>
53+
</template>
54+
```
55+
56+
```vue
57+
<template>
58+
<button role="presentation">press me</button>
59+
</template>
60+
```
61+
```vue
62+
<template>
63+
<a href="#" role="presentation">press me</a>
64+
</template>
65+
```
66+
```vue
67+
<template>
68+
<div role="presentation">
69+
<button>press me</button>
70+
</div>
71+
</template>
72+
```
73+
```vue
74+
<template>
75+
<span tabindex='0' role="presentation"><em>Icon</em></span>
76+
</template>
77+
```

src/rules/__tests__/no-presentation-role-or-aria-hidden-on-focusable.test.ts renamed to src/rules/__tests__/no-aria-hidden-on-focusable.test.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
1-
import rule from '../no-presentation-role-or-aria-hidden-on-focusable';
1+
import rule from '../no-aria-hidden-on-focusable';
22
import makeRuleTester from "./makeRuleTester";
33

44
makeRuleTester('no-presentation-role-or-aria-hidden-on-focusable', rule, {
55
valid: [
66
"<button>Submit</button>",
7-
"<div aria-hidden='true'><span>Some text</div></div>",
7+
"<div aria-hidden='true'><button tabindex='-1'>Some text</button></div>",
88
"<div><button>Submit</button></div>",
9-
"<a href='#'>link</a>",
10-
"<button tabindex='-1' aria-hidden='true' role='presentation'>Press</button>",
9+
"<a href='#' tabindex='-1'>link</a>",
10+
"<button tabindex='-1' aria-hidden='true'>Press</button>",
1111
"<div aria-hidden='true'><a href='#' tabindex='-1'>Link</a></div>"
1212
],
1313
invalid: [
1414
{
1515
code: "<div aria-hidden='true'><button>Submit</button></div>",
1616
errors: [{messageId: "default"}]
1717
},
18-
{
19-
code: "<button type='button' role='presentation'>Submit</button>",
20-
errors: [{messageId: "default"}]
21-
},
2218
{
2319
code: "<button type='button' aria-hidden='true'>Submit</button>",
2420
errors: [{messageId: "default"}]
@@ -28,7 +24,7 @@ makeRuleTester('no-presentation-role-or-aria-hidden-on-focusable', rule, {
2824
errors: [{messageId: "default"}]
2925
},
3026
{
31-
code: "<span tabindex='0' role='presentation'><em>Icon</em></span>",
27+
code: "<span tabindex='0' aria-hidden='true'><em>Icon</em></span>",
3228
errors: [{messageId: "default"}]
3329
}
3430
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import rule from '../no-role-presentation-on-focusable';
2+
import makeRuleTester from "./makeRuleTester";
3+
4+
makeRuleTester('no-role-presentation-role-on-focusable', rule, {
5+
valid: [
6+
"<button>Submit</button>",
7+
"<div role='presentation'><button tabindex='-1'>Some text</button></div>",
8+
"<div><button>Submit</button></div>",
9+
"<a href='#' tabindex='-1'>link</a>",
10+
"<button tabindex='-1' role='presentation'>Press</button>",
11+
"<div role='presentation'><a href='#' tabindex='-1'>Link</a></div>"
12+
],
13+
invalid: [
14+
{
15+
code: "<div role='presentation'><button>Submit</button></div>",
16+
errors: [{messageId: "default"}]
17+
},
18+
{
19+
code: "<button type='button' role='presentation'>Submit</button>",
20+
errors: [{messageId: "default"}]
21+
},
22+
{
23+
code: "<a href='#' role='presentation'>Link</a>",
24+
errors: [{messageId: "default"}]
25+
},
26+
{
27+
code: "<span tabindex='0' role='presentation'><em>Icon</em></span>",
28+
errors: [{messageId: "default"}]
29+
}
30+
]
31+
})
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { Rule } from "eslint";
2+
3+
import { defineTemplateBodyVisitor, getElementAttributeValue, makeDocsURL } from "../utils";
4+
import hasFocusableElements from "../utils/hasFocusableElement";
5+
6+
const rule: Rule.RuleModule = {
7+
meta: {
8+
type: "problem",
9+
docs: {
10+
url: makeDocsURL("no-aria-hidden-on-focusable")
11+
},
12+
messages: {
13+
default: "Focusable/Interactive elements must not have an aria-hidden attribute."
14+
},
15+
schema: []
16+
},
17+
create(context) {
18+
return defineTemplateBodyVisitor(context, {
19+
VElement(node) {
20+
const hasAriaHidden = getElementAttributeValue(node, 'aria-hidden');
21+
if (hasAriaHidden) {
22+
if (hasFocusableElements(node)) {
23+
context.report({
24+
node: node as any,
25+
messageId: 'default',
26+
});
27+
}
28+
}
29+
},
30+
});
31+
}
32+
}
33+
34+
export default rule;

src/rules/no-presentation-role-or-aria-hidden-on-focusable.ts

-55
This file was deleted.

0 commit comments

Comments
 (0)