Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(name-rules): ignore when explicit roles don't require a name #2629

Merged
merged 2 commits into from
Nov 9, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion doc/standards-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ The [`ariaRoles`](../lib/standards/aria-roles.js) object defines valid ARIA role
- `requiredOwned` - array(optional). List of required owned roles.
- `requiredAttrs` - array(optional). List of required attributes.
- `allowedAttrs` - array(optional). List of allowed attributes (besides any required and global ARIA attributes).
- `superclassRole` - array(optional). List of superclass roles.
- `accessibleNameDrequired` - boolean(optional. Default `false`). If elements with this role require an accessible name.
WilcoFiers marked this conversation as resolved.
Show resolved Hide resolved
- `nameFromContent` - boolean(optional. Default `false`). If the role allows name from content when calculating the accessible name.
- `unsupported` - boolean(optional. Default `false`). If the role role is unsupported. Use this property to disable a role.
- `unsupported` - boolean(optional. Default `false`). If the role is unsupported. Use this property to disable a role.

### Dpub Roles

Expand Down
2 changes: 2 additions & 0 deletions lib/core/base/metadata-function-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ import layoutTableMatches from '../../rules/layout-table-matches';
import linkInTextBlockMatches from '../../rules/link-in-text-block-matches';
import noAutoplayAudioMatches from '../../rules/no-autoplay-audio-matches';
import noEmptyRoleMatches from '../../rules/no-empty-role-matches';
import noExplicitNameRequiredMatches from '../../rules/no-explicit-name-required-matches';
import noNamingMethodMatches from '../../rules/no-naming-method-matches';
import noRoleMatches from '../../rules/no-role-matches';
import notHtmlMatches from '../../rules/not-html-matches';
Expand Down Expand Up @@ -321,6 +322,7 @@ const metadataFunctionMap = {
'link-in-text-block-matches': linkInTextBlockMatches,
'no-autoplay-audio-matches': noAutoplayAudioMatches,
'no-empty-role-matches': noEmptyRoleMatches,
'no-explicit-name-required-matches': noExplicitNameRequiredMatches,
'no-naming-method-matches': noNamingMethodMatches,
'no-role-matches': noRoleMatches,
'not-html-matches': notHtmlMatches,
Expand Down
1 change: 1 addition & 0 deletions lib/rules/button-name.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"id": "button-name",
"selector": "button",
"matches": "no-explicit-name-required-matches",
"tags": [
"cat.name-role-value",
"wcag2a",
Expand Down
1 change: 1 addition & 0 deletions lib/rules/image-alt.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"id": "image-alt",
"selector": "img",
"matches": "no-explicit-name-required-matches",
"tags": [
"cat.text-alternatives",
"wcag2a",
Expand Down
1 change: 1 addition & 0 deletions lib/rules/input-button-name.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"id": "input-button-name",
"selector": "input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"]",
"matches": "no-explicit-name-required-matches",
"tags": [
"cat.name-role-value",
"wcag2a",
Expand Down
1 change: 1 addition & 0 deletions lib/rules/input-image-alt.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"id": "input-image-alt",
"selector": "input[type=\"image\"]",
"matches": "no-explicit-name-required-matches",
"tags": [
"cat.text-alternatives",
"wcag2a",
Expand Down
22 changes: 22 additions & 0 deletions lib/rules/no-explicit-name-required-matches.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { isFocusable } from '../commons/dom';
import { getExplicitRole } from '../commons/aria';
import ariaRoles from '../standards/aria-roles';

/**
* Filter out elements with an explicit role that does not require an accessible name and is not focusable
*/
function noExplicitNameRequired(node, virtualNode) {
const role = getExplicitRole(virtualNode);
if (!role || ['none', 'presentation'].includes(role)) {
return true;
}

const { accessibleNameRequired } = ariaRoles[role] || {};
if (accessibleNameRequired || isFocusable(virtualNode)) {
return true;
}

return false;
}

export default noExplicitNameRequired;
1 change: 1 addition & 0 deletions lib/rules/object-alt.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"id": "object-alt",
"selector": "object",
"matches": "no-explicit-name-required-matches",
"tags": [
"cat.text-alternatives",
"wcag2a",
Expand Down
81 changes: 62 additions & 19 deletions lib/standards/aria-roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ const ariaRoles = {
alertdialog: {
type: 'widget',
allowedAttrs: ['aria-expanded', 'aria-modal'],
superclassRole: ['alert', 'dialog']
superclassRole: ['alert', 'dialog'],
accessibleNameRequired: true
},
application: {
// Note: spec difference
type: 'landmark',
// Note: aria-expanded is not in the 1.1 spec but is
// consistently supported in ATs and was added in 1.2
allowedAttrs: ['aria-activedescendant', 'aria-expanded'],
superclassRole: ['structure']
superclassRole: ['structure'],
accessibleNameRequired: true
},
article: {
type: 'structure',
Expand All @@ -52,6 +54,7 @@ const ariaRoles = {
type: 'widget',
allowedAttrs: ['aria-expanded', 'aria-pressed'],
superclassRole: ['command'],
accessibleNameRequired: true,
nameFromContent: true
},
caption: {
Expand Down Expand Up @@ -82,6 +85,7 @@ const ariaRoles = {
// consistently supported in ATs and was added in 1.2
allowedAttrs: ['aria-checked', 'aria-readonly', 'aria-required'],
superclassRole: ['input'],
accessibleNameRequired: true,
nameFromContent: true
},
code: {
Expand All @@ -103,6 +107,8 @@ const ariaRoles = {
'aria-selected'
],
superclassRole: ['cell', 'gridcell', 'sectionhead'],
// Note: spec difference
accessibleNameRequired: false,
nameFromContent: true
},
combobox: {
Expand All @@ -120,7 +126,8 @@ const ariaRoles = {
'aria-activedescendant',
'aria-orientation'
],
superclassRole: ['select']
superclassRole: ['select'],
accessibleNameRequired: true
},
command: {
type: 'abstract',
Expand Down Expand Up @@ -152,7 +159,8 @@ const ariaRoles = {
dialog: {
type: 'widget',
allowedAttrs: ['aria-expanded', 'aria-modal'],
superclassRole: ['window']
superclassRole: ['window'],
accessibleNameRequired: true
},
directory: {
type: 'structure',
Expand Down Expand Up @@ -200,7 +208,9 @@ const ariaRoles = {
'aria-expanded',
'aria-rowcount'
],
superclassRole: ['composite', 'table']
superclassRole: ['composite', 'table'],
// Note: spec difference
accessibleNameRequired: false
},
gridcell: {
type: 'widget',
Expand Down Expand Up @@ -228,12 +238,15 @@ const ariaRoles = {
requiredAttrs: ['aria-level'],
allowedAttrs: ['aria-expanded'],
superclassRole: ['sectionhead'],
// Note: spec difference
accessibleNameRequired: false,
nameFromContent: true
},
img: {
type: 'structure',
allowedAttrs: ['aria-expanded'],
superclassRole: ['section']
superclassRole: ['section'],
accessibleNameRequired: true
},
input: {
type: 'abstract',
Expand All @@ -251,6 +264,7 @@ const ariaRoles = {
type: 'widget',
allowedAttrs: ['aria-expanded'],
superclassRole: ['command'],
accessibleNameRequired: true,
nameFromContent: true
},
list: {
Expand All @@ -270,7 +284,8 @@ const ariaRoles = {
'aria-expanded',
'aria-orientation'
],
superclassRole: ['select']
superclassRole: ['select'],
accessibleNameRequired: true
},
listitem: {
type: 'structure',
Expand Down Expand Up @@ -332,6 +347,7 @@ const ariaRoles = {
// consistently supported in ATs and was added in 1.2
allowedAttrs: ['aria-posinset', 'aria-setsize', 'aria-expanded'],
superclassRole: ['command'],
accessibleNameRequired: true,
nameFromContent: true
},
menuitemcheckbox: {
Expand All @@ -344,6 +360,7 @@ const ariaRoles = {
'aria-setsize'
],
superclassRole: ['checkbox', 'menuitem'],
accessibleNameRequired: true,
nameFromContent: true
},
menuitemradio: {
Expand All @@ -356,13 +373,15 @@ const ariaRoles = {
'aria-setsize'
],
superclassRole: ['menuitemcheckbox', 'radio'],
accessibleNameRequired: true,
nameFromContent: true
},
meter: {
type: 'structure',
allowedAttrs: ['aria-valuetext'],
requiredAttrs: ['aria-valuemax', 'aria-valuemin', 'aria-valuenow'],
superclassRole: ['range']
superclassRole: ['range'],
accessibleNameRequired: true
},
navigation: {
type: 'landmark',
Expand Down Expand Up @@ -391,6 +410,7 @@ const ariaRoles = {
'aria-setsize'
],
superclassRole: ['input'],
accessibleNameRequired: true,
nameFromContent: true
},
paragraph: {
Expand All @@ -410,7 +430,8 @@ const ariaRoles = {
'aria-valuenow',
'aria-valuetext'
],
superclassRole: ['range']
superclassRole: ['range'],
accessibleNameRequired: true
},
radio: {
type: 'widget',
Expand All @@ -427,6 +448,7 @@ const ariaRoles = {
'aria-required'
],
superclassRole: ['input'],
accessibleNameRequired: true,
nameFromContent: true
},
radiogroup: {
Expand All @@ -439,7 +461,9 @@ const ariaRoles = {
'aria-expanded',
'aria-orientation'
],
superclassRole: ['select']
superclassRole: ['select'],
// Note: spec difference
accessibleNameRequired: false
},
range: {
type: 'abstract',
Expand All @@ -448,7 +472,9 @@ const ariaRoles = {
region: {
type: 'landmark',
allowedAttrs: ['aria-expanded'],
superclassRole: ['landmark']
superclassRole: ['landmark'],
// Note: spec difference
accessibleNameRequired: false
},
roletype: {
type: 'abstract',
Expand Down Expand Up @@ -491,6 +517,8 @@ const ariaRoles = {
'aria-selected'
],
superclassRole: ['cell', 'gridcell', 'sectionhead'],
// Note: spec difference
accessibleNameRequired: false,
nameFromContent: true
},
scrollbar: {
Expand Down Expand Up @@ -527,7 +555,8 @@ const ariaRoles = {
'aria-readonly',
'aria-required'
],
superclassRole: ['textbox']
superclassRole: ['textbox'],
accessibleNameRequired: true
},
section: {
type: 'abstract',
Expand Down Expand Up @@ -573,7 +602,8 @@ const ariaRoles = {
'aria-readonly',
'aria-valuetext'
],
superclassRole: ['input', 'range']
superclassRole: ['input', 'range'],
accessibleNameRequired: true
},
spinbutton: {
type: 'widget',
Expand All @@ -589,7 +619,8 @@ const ariaRoles = {
'aria-activedescendant',
'aria-valuetext'
],
superclassRole: ['composite', 'input', 'range']
superclassRole: ['composite', 'input', 'range'],
accessibleNameRequired: true
},
status: {
type: 'widget',
Expand Down Expand Up @@ -617,6 +648,7 @@ const ariaRoles = {
requiredAttrs: ['aria-checked'],
allowedAttrs: ['aria-readonly'],
superclassRole: ['checkbox'],
accessibleNameRequired: true,
nameFromContent: true
},
tab: {
Expand All @@ -640,6 +672,8 @@ const ariaRoles = {
// table be named from content (we even had to special case
// table in commons/aria/named-from-contents)
superclassRole: ['section'],
// Note: spec difference
accessibleNameRequired: false,
nameFromContent: true
},
tablist: {
Expand All @@ -659,7 +693,9 @@ const ariaRoles = {
tabpanel: {
type: 'widget',
allowedAttrs: ['aria-expanded'],
superclassRole: ['section']
superclassRole: ['section'],
// Note: spec difference
accessibleNameRequired: false
},
term: {
type: 'structure',
Expand All @@ -678,7 +714,8 @@ const ariaRoles = {
'aria-readonly',
'aria-required'
],
superclassRole: ['input']
superclassRole: ['input'],
accessibleNameRequired: true
},
time: {
type: 'structure',
Expand All @@ -696,7 +733,8 @@ const ariaRoles = {
'aria-activedescendant',
'aria-expanded'
],
superclassRole: ['group']
superclassRole: ['group'],
accessibleNameRequired: true
},
tooltip: {
type: 'structure',
Expand All @@ -714,7 +752,9 @@ const ariaRoles = {
'aria-expanded',
'aria-orientation'
],
superclassRole: ['select']
superclassRole: ['select'],
// Note: spec difference
accessibleNameRequired: false
},
treegrid: {
type: 'composite',
Expand All @@ -730,7 +770,9 @@ const ariaRoles = {
'aria-required',
'aria-rowcount'
],
superclassRole: ['grid', 'tree']
superclassRole: ['grid', 'tree'],
// Note: spec difference
accessibleNameRequired: false
},
treeitem: {
type: 'widget',
Expand All @@ -744,6 +786,7 @@ const ariaRoles = {
'aria-setsize'
],
superclassRole: ['listitem', 'option'],
accessibleNameRequired: true,
nameFromContent: true
},
widget: {
Expand Down
Loading