Skip to content

Commit

Permalink
[fix] Suppress a11y-no-noninteractive-tabindex warning if an elemen…
Browse files Browse the repository at this point in the history
…t has a `tabpanel` (#8025)

* update tabindex warning to ignore tabpanels

* refactor

Co-authored-by: Yuichiro Yamashita <xydybaseball@gmail.com>
  • Loading branch information
bertybot and baseballyama committed Dec 5, 2022
1 parent de46e36 commit ed3ac92
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 40 deletions.
25 changes: 5 additions & 20 deletions src/compiler/compile/utils/a11y.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import {
import { AXObjects, AXObjectRoles, elementAXObjects } from 'axobject-query';
import Attribute from '../nodes/Attribute';

const roles = [...roles_map.keys()];
const non_abstract_roles = [...roles_map.keys()].filter((name) => !roles_map.get(name).abstract);

const non_interactive_roles = new Set(
roles
non_abstract_roles
.filter((name) => {
const role = roles_map.get(name);
return (
!roles_map.get(name).abstract &&
// 'toolbar' does not descend from widget, but it does support
// aria-activedescendant, thus in practice we treat it as a widget.
name !== 'toolbar' &&
// focusable tabpanel elements are recommended if any panels in a set contain content where the first element in the panel is not focusable.
!['toolbar', 'tabpanel'].includes(name) &&
!role.superClass.some((classes) => classes.includes('widget'))
);
})
Expand All @@ -29,22 +29,7 @@ const non_interactive_roles = new Set(
);

const interactive_roles = new Set(
roles
.filter((name) => {
const role = roles_map.get(name);
return (
!role.abstract &&
// The `progressbar` is descended from `widget`, but in practice, its
// value is always `readonly`, so we treat it as a non-interactive role.
name !== 'progressbar' &&
role.superClass.some((classes) => classes.includes('widget'))
);
})
.concat(
// 'toolbar' does not descend from widget, but it does support
// aria-activedescendant, thus in practice we treat it as a widget.
'toolbar'
)
non_abstract_roles.filter((name) => !non_interactive_roles.has(name))
);

export function is_non_interactive_roles(role: ARIARoleDefintionKey) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<div role='button' tabindex='0' />
<div role='article' tabindex='-1' />
<article tabindex='-1' />
<div role="tabpanel" tabindex='0' />
<!-- invalid -->
<div tabindex='0' />
<div role='article' tabindex='0' />
Expand Down
40 changes: 20 additions & 20 deletions test/validator/samples/a11y-no-nointeractive-tabindex/warnings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,61 @@
{
"code": "a11y-no-noninteractive-tabindex",
"end": {
"character": 241,
"character": 278,
"column": 20,
"line": 11
"line": 12
},
"message": "A11y: noninteractive element cannot have positive tabIndex value",
"pos": 221,
"pos": 258,
"start": {
"character": 221,
"character": 258,
"column": 0,
"line": 11
"line": 12
}
},
{
"code": "a11y-no-noninteractive-tabindex",
"end": {
"character": 277,
"character": 314,
"column": 35,
"line": 12
"line": 13
},
"message": "A11y: noninteractive element cannot have positive tabIndex value",
"pos": 242,
"pos": 279,
"start": {
"character": 242,
"character": 279,
"column": 0,
"line": 12
"line": 13
}
},
{
"code": "a11y-no-noninteractive-tabindex",
"end": {
"character": 302,
"character": 339,
"column": 24,
"line": 13
"line": 14
},
"message": "A11y: noninteractive element cannot have positive tabIndex value",
"pos": 278,
"pos": 315,
"start": {
"character": 278,
"character": 315,
"column": 0,
"line": 13
"line": 14
}
},
{
"code": "a11y-no-noninteractive-tabindex",
"end": {
"character": 329,
"character": 366,
"column": 26,
"line": 14
"line": 15
},
"message": "A11y: noninteractive element cannot have positive tabIndex value",
"pos": 303,
"pos": 340,
"start": {
"character": 303,
"character": 340,
"column": 0,
"line": 14
"line": 15
}
}
]

0 comments on commit ed3ac92

Please sign in to comment.