diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 48ea0ec3e1..9d5328ecb5 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -434,12 +434,17 @@ export default class Element extends Node { } validate_attributes_a11y() { - const { component, attributes } = this; + const { component, attributes, handlers } = this; const attribute_map = new Map(); + const handlers_map = new Map(); + attributes.forEach(attribute => ( attribute_map.set(attribute.name, attribute) )); + handlers.forEach(handler => ( + handlers_map.set(handler.name, handler) + )); attributes.forEach(attribute => { if (attribute.is_spread) return; @@ -550,6 +555,21 @@ export default class Element extends Node { } }); + // click-events-have-key-events + if (handlers_map.has("click")) { + const hasKeyEvent = + handlers_map.has("keydown") || + handlers_map.has("keyup") || + handlers_map.has("keypress"); + + if (!hasKeyEvent) { + component.warn(this, { + code: `a11y-click-events-have-key-events`, + message: `A11y: on:click event must be accompanied by on:keydown, on:keyup or on:keypress event` + }); + } + } + // no-noninteractive-tabindex if (!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'); diff --git a/test/validator/samples/a11y-click-events-have-key-events/input.svelte b/test/validator/samples/a11y-click-events-have-key-events/input.svelte new file mode 100644 index 0000000000..4517d6709a --- /dev/null +++ b/test/validator/samples/a11y-click-events-have-key-events/input.svelte @@ -0,0 +1,15 @@ + + + +
+ + +
+
+
+
+
+
+
diff --git a/test/validator/samples/a11y-click-events-have-key-events/warnings.json b/test/validator/samples/a11y-click-events-have-key-events/warnings.json new file mode 100644 index 0000000000..a08b52c114 --- /dev/null +++ b/test/validator/samples/a11y-click-events-have-key-events/warnings.json @@ -0,0 +1,17 @@ +[ + { + "code": "a11y-click-events-have-key-events", + "message": "A11y: on:click event must be accompanied by on:keydown, on:keyup or on:keypress event", + "end": { + "character": 85, + "column": 23, + "line": 6 + }, + "start": { + "character": 62, + "column": 0, + "line": 6 + }, + "pos": 62 + } +]