Skip to content

Commit

Permalink
fix: hide some a11y warnings for <svelte:element> tags
Browse files Browse the repository at this point in the history
Some a11y warnings only work on specific tags, which results in potential false positives for `<svelte:element>` tags - silence those
closes sveltejs#7939
  • Loading branch information
dummdidumm committed Feb 27, 2023
1 parent b5ec863 commit 9140a9c
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/compiler/compile/compiler_warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,10 @@ export default {
code: 'a11y-mouse-events-have-key-events',
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',
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) => ({
code: 'a11y-missing-content',
message: `A11y: <${name}> element should have child content`
Expand Down
11 changes: 6 additions & 5 deletions src/compiler/compile/nodes/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ export default class Element extends Node {
}

// 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);
}
}
Expand Down Expand Up @@ -590,7 +590,7 @@ export default class Element extends Node {
}

// 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);
if (role) {
const required_role_props = Object.keys(role.requiredProps);
Expand Down Expand Up @@ -622,7 +622,7 @@ export default class Element extends Node {
}

// 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);
}

Expand All @@ -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);

if (
!this.is_dynamic_element &&
!is_hidden_from_screen_reader(this.name, attribute_map) &&
(!role || is_non_presentation_role) &&
!is_interactive_element(this.name, attribute_map) &&
Expand All @@ -655,14 +656,14 @@ export default class Element extends Node {
if (!has_key_event) {
component.warn(
this,
compiler_warnings.a11y_click_events_have_key_events()
compiler_warnings.a11y_click_events_have_key_events
);
}
}
}

// 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');
if (tab_index && (!tab_index.is_static || Number(tab_index.get_static_value()) >= 0)) {
component.warn(this, compiler_warnings.a11y_no_noninteractive_tabindex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
<input aria-activedescendant="some-id" tabindex="0" />
<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 aria-activedescendant="some-id" role="tablist" tabindex={-1} />
<div aria-activedescendant="some-id" role="tablist" tabindex="-1" />

<!-- INVALID -->
<div aria-activedescendant="some-id" />

Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@
<div on:click={noop} role="presentation" />
<div on:click={noop} role="none" />
<div on:click={noop} role={dynamicRole} />

<svelte:element this={Math.random() ? 'button' : 'div'} on:click={noop} />
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<div role='article' tabindex='-1' />
<article tabindex='-1' />
<div role="tabpanel" tabindex='0' />
<svelte:element this={Math.random() ? 'button' : 'div'} tabindex="0" />
<!-- invalid -->
<div tabindex='0' />
<div role='article' tabindex='0' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,48 @@
"code": "a11y-no-noninteractive-tabindex",
"end": {
"column": 20,
"line": 12
"line": 13
},
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": {
"column": 0,
"line": 12
"line": 13
}
},
{
"code": "a11y-no-noninteractive-tabindex",
"end": {
"column": 35,
"line": 13
"line": 14
},
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": {
"column": 0,
"line": 13
"line": 14
}
},
{
"code": "a11y-no-noninteractive-tabindex",
"end": {
"column": 24,
"line": 14
"line": 15
},
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": {
"column": 0,
"line": 14
"line": 15
}
},
{
"code": "a11y-no-noninteractive-tabindex",
"end": {
"column": 26,
"line": 15
"line": 16
},
"message": "A11y: noninteractive element cannot have nonnegative tabIndex value",
"start": {
"column": 0,
"line": 15
"line": 16
}
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
<div role="meter" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
<div role="scrollbar" aria-controls="panel" aria-valuenow="50"></div>
<input role="switch" type="checkbox" />
<svelte:element this={Math.random() ? 'input' : 'div'} role="checkbox" />
7 changes: 6 additions & 1 deletion test/validator/samples/a11y-scope/input.svelte
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
<div scope/>
<!-- valid -->
<th scope />
<svelte:element this={Math.random() ? 'th' : 'td'} scope />

<!-- invalid -->
<div scope/>
4 changes: 2 additions & 2 deletions test/validator/samples/a11y-scope/warnings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"code": "a11y-misplaced-scope",
"message": "A11y: The scope attribute should only be used with <th> elements",
"start": {
"line": 1,
"line": 6,
"column": 5
},
"end": {
"line": 1,
"line": 6,
"column": 10
}
}
Expand Down

0 comments on commit 9140a9c

Please sign in to comment.