fix: hide some a11y warnings for `<svelte:element>` tags (#8335)

Some a11y warnings only work on specific tags, which results in potential false positives for `<svelte:element>` tags - silence those
closes #7939
pull/7774/head
Simon H 2 years ago committed by GitHub
parent f1c9168aef
commit 60db05da86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -186,10 +186,10 @@ export default {
code: 'a11y-mouse-events-have-key-events', code: 'a11y-mouse-events-have-key-events',
message: `A11y: on:${event} must be accompanied by on:${accompanied_by}` message: `A11y: on:${event} must be accompanied by on:${accompanied_by}`
}), }),
a11y_click_events_have_key_events: () => ({ a11y_click_events_have_key_events: {
code: 'a11y-click-events-have-key-events', code: 'a11y-click-events-have-key-events',
message: 'A11y: visible, non-interactive elements with an on:click event must be accompanied by an on:keydown, on:keyup, or on:keypress event.' message: 'A11y: visible, non-interactive elements with an on:click event must be accompanied by an on:keydown, on:keyup, or on:keypress event.'
}), },
a11y_missing_content: (name: string) => ({ a11y_missing_content: (name: string) => ({
code: 'a11y-missing-content', code: 'a11y-missing-content',
message: `A11y: <${name}> element should have child content` message: `A11y: <${name}> element should have child content`

@ -550,7 +550,7 @@ export default class Element extends Node {
} }
// aria-activedescendant-has-tabindex // aria-activedescendant-has-tabindex
if (name === 'aria-activedescendant' && !is_interactive_element(this.name, attribute_map) && !attribute_map.has('tabindex')) { if (name === 'aria-activedescendant' && !this.is_dynamic_element && !is_interactive_element(this.name, attribute_map) && !attribute_map.has('tabindex')) {
component.warn(attribute, compiler_warnings.a11y_aria_activedescendant_has_tabindex); component.warn(attribute, compiler_warnings.a11y_aria_activedescendant_has_tabindex);
} }
} }
@ -590,7 +590,7 @@ export default class Element extends Node {
} }
// role-has-required-aria-props // role-has-required-aria-props
if (!is_semantic_role_element(current_role, this.name, attribute_map)) { if (!this.is_dynamic_element && !is_semantic_role_element(current_role, this.name, attribute_map)) {
const role = roles.get(current_role); const role = roles.get(current_role);
if (role) { if (role) {
const required_role_props = Object.keys(role.requiredProps); const required_role_props = Object.keys(role.requiredProps);
@ -622,7 +622,7 @@ export default class Element extends Node {
} }
// scope // scope
if (name === 'scope' && this.name !== 'th') { if (name === 'scope' && !this.is_dynamic_element && this.name !== 'th') {
component.warn(attribute, compiler_warnings.a11y_misplaced_scope); component.warn(attribute, compiler_warnings.a11y_misplaced_scope);
} }
@ -642,6 +642,7 @@ export default class Element extends Node {
const is_non_presentation_role = role?.is_static && !is_presentation_role(role.get_static_value() as ARIARoleDefintionKey); const is_non_presentation_role = role?.is_static && !is_presentation_role(role.get_static_value() as ARIARoleDefintionKey);
if ( if (
!this.is_dynamic_element &&
!is_hidden_from_screen_reader(this.name, attribute_map) && !is_hidden_from_screen_reader(this.name, attribute_map) &&
(!role || is_non_presentation_role) && (!role || is_non_presentation_role) &&
!is_interactive_element(this.name, attribute_map) && !is_interactive_element(this.name, attribute_map) &&
@ -655,14 +656,14 @@ export default class Element extends Node {
if (!has_key_event) { if (!has_key_event) {
component.warn( component.warn(
this, this,
compiler_warnings.a11y_click_events_have_key_events() compiler_warnings.a11y_click_events_have_key_events
); );
} }
} }
} }
// no-noninteractive-tabindex // no-noninteractive-tabindex
if (!is_interactive_element(this.name, attribute_map) && !is_interactive_roles(attribute_map.get('role')?.get_static_value() as ARIARoleDefintionKey)) { if (!this.is_dynamic_element && !is_interactive_element(this.name, attribute_map) && !is_interactive_roles(attribute_map.get('role')?.get_static_value() as ARIARoleDefintionKey)) {
const tab_index = attribute_map.get('tabindex'); const tab_index = attribute_map.get('tabindex');
if (tab_index && (!tab_index.is_static || Number(tab_index.get_static_value()) >= 0)) { if (tab_index && (!tab_index.is_static || Number(tab_index.get_static_value()) >= 0)) {
component.warn(this, compiler_warnings.a11y_no_noninteractive_tabindex); component.warn(this, compiler_warnings.a11y_no_noninteractive_tabindex);

@ -7,11 +7,10 @@
<input aria-activedescendant="some-id" tabindex="0" /> <input aria-activedescendant="some-id" tabindex="0" />
<input aria-activedescendant="some-id" tabindex={-1} /> <input aria-activedescendant="some-id" tabindex={-1} />
<input aria-activedescendant="some-id" tabindex="-1" /> <input aria-activedescendant="some-id" tabindex="-1" />
<svelte:element this={Math.random() ? 'input' : 'button'} aria-activedescendant="some-id" />
<div /> <div />
<div aria-activedescendant="some-id" role="tablist" tabindex={-1} /> <div aria-activedescendant="some-id" role="tablist" tabindex={-1} />
<div aria-activedescendant="some-id" role="tablist" tabindex="-1" /> <div aria-activedescendant="some-id" role="tablist" tabindex="-1" />
<!-- INVALID --> <!-- INVALID -->
<div aria-activedescendant="some-id" /> <div aria-activedescendant="some-id" />

@ -47,3 +47,5 @@
<div on:click={noop} role="presentation" /> <div on:click={noop} role="presentation" />
<div on:click={noop} role="none" /> <div on:click={noop} role="none" />
<div on:click={noop} role={dynamicRole} /> <div on:click={noop} role={dynamicRole} />
<svelte:element this={Math.random() ? 'button' : 'div'} on:click={noop} />

@ -8,6 +8,7 @@
<div role='article' tabindex='-1' /> <div role='article' tabindex='-1' />
<article tabindex='-1' /> <article tabindex='-1' />
<div role="tabpanel" tabindex='0' /> <div role="tabpanel" tabindex='0' />
<svelte:element this={Math.random() ? 'button' : 'div'} tabindex="0" />
<!-- invalid --> <!-- invalid -->
<div tabindex='0' /> <div tabindex='0' />
<div role='article' tabindex='0' /> <div role='article' tabindex='0' />

@ -3,48 +3,48 @@
"code": "a11y-no-noninteractive-tabindex", "code": "a11y-no-noninteractive-tabindex",
"end": { "end": {
"column": 20, "column": 20,
"line": 12 "line": 13
}, },
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value", "message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": { "start": {
"column": 0, "column": 0,
"line": 12 "line": 13
} }
}, },
{ {
"code": "a11y-no-noninteractive-tabindex", "code": "a11y-no-noninteractive-tabindex",
"end": { "end": {
"column": 35, "column": 35,
"line": 13 "line": 14
}, },
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value", "message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": { "start": {
"column": 0, "column": 0,
"line": 13 "line": 14
} }
}, },
{ {
"code": "a11y-no-noninteractive-tabindex", "code": "a11y-no-noninteractive-tabindex",
"end": { "end": {
"column": 24, "column": 24,
"line": 14 "line": 15
}, },
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value", "message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": { "start": {
"column": 0, "column": 0,
"line": 14 "line": 15
} }
}, },
{ {
"code": "a11y-no-noninteractive-tabindex", "code": "a11y-no-noninteractive-tabindex",
"end": { "end": {
"column": 26, "column": 26,
"line": 15 "line": 16
}, },
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value", "message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": { "start": {
"column": 0, "column": 0,
"line": 15 "line": 16
} }
} }
] ]

@ -8,3 +8,4 @@
<div role="meter" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div> <div role="meter" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
<div role="scrollbar" aria-controls="panel" aria-valuenow="50"></div> <div role="scrollbar" aria-controls="panel" aria-valuenow="50"></div>
<input role="switch" type="checkbox" /> <input role="switch" type="checkbox" />
<svelte:element this={Math.random() ? 'input' : 'div'} role="checkbox" />

@ -1 +1,6 @@
<div scope/> <!-- valid -->
<th scope />
<svelte:element this={Math.random() ? 'th' : 'td'} scope />
<!-- invalid -->
<div scope/>

@ -3,11 +3,11 @@
"code": "a11y-misplaced-scope", "code": "a11y-misplaced-scope",
"message": "A11y: The scope attribute should only be used with <th> elements", "message": "A11y: The scope attribute should only be used with <th> elements",
"start": { "start": {
"line": 1, "line": 6,
"column": 5 "column": 5
}, },
"end": { "end": {
"line": 1, "line": 6,
"column": 10 "column": 10
} }
} }

Loading…
Cancel
Save