diff --git a/site/content/docs/06-accessibility-warnings.md b/site/content/docs/06-accessibility-warnings.md index 8d3d44a94e..7aa3873cce 100644 --- a/site/content/docs/06-accessibility-warnings.md +++ b/site/content/docs/06-accessibility-warnings.md @@ -19,6 +19,18 @@ Enforce no `accesskey` on element. Access keys are HTML attributes that allow we --- +### `a11y-aria-activedescendant-has-tabindex` + +An element with `aria-activedescendant` must be tabbable, so it must either have an inherent `tabindex` or declare `tabindex` as an attribute. + +```sv + +
+ +``` + +--- + ### `a11y-aria-attributes` Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `aria-*` props. diff --git a/src/compiler/compile/compiler_warnings.ts b/src/compiler/compile/compiler_warnings.ts index 3f552eb8b8..a10fe6155c 100644 --- a/src/compiler/compile/compiler_warnings.ts +++ b/src/compiler/compile/compiler_warnings.ts @@ -187,6 +187,10 @@ export default { code: 'a11y-no-noninteractive-tabindex', message: 'A11y: noninteractive element cannot have nonnegative tabIndex value' }, + a11y_aria_activedescendant_has_tabindex: { + code: 'a11y-aria-activedescendant-has-tabindex', + message: 'A11y: Elements with attribute aria-activedescendant should have tabindex value' + }, redundant_event_modifier_for_touch: { code: 'redundant-event-modifier', message: 'Touch event handlers that don\'t use the \'event\' object are passive by default' diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 62e0de51bf..8635355a12 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -484,6 +484,11 @@ export default class Element extends Node { component.warn(attribute, compiler_warnings.a11y_incorrect_attribute_type(schema, name)); } } + + // aria-activedescendant-has-tabindex + if (name === 'aria-activedescendant' && !is_interactive_element(this.name, attribute_map) && !attribute_map.has('tabindex')) { + component.warn(attribute, compiler_warnings.a11y_aria_activedescendant_has_tabindex); + } } // aria-role diff --git a/test/validator/samples/a11y-aria-activedescendant/input.svelte b/test/validator/samples/a11y-aria-activedescendant/input.svelte new file mode 100644 index 0000000000..22570e8c50 --- /dev/null +++ b/test/validator/samples/a11y-aria-activedescendant/input.svelte @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/test/validator/samples/a11y-aria-activedescendant/warnings.json b/test/validator/samples/a11y-aria-activedescendant/warnings.json new file mode 100644 index 0000000000..8749c1c125 --- /dev/null +++ b/test/validator/samples/a11y-aria-activedescendant/warnings.json @@ -0,0 +1,17 @@ +[ + { + "code": "a11y-aria-activedescendant-has-tabindex", + "end": { + "character": 568, + "column": 36, + "line": 16 + }, + "message": "A11y: Elements with attribute aria-activedescendant should have tabindex value", + "pos": 537, + "start": { + "character": 537, + "column": 5, + "line": 16 + } + } +]