Event Handler On A Non-Interactive Element
ID |
javascript.jsx_non_interactive_element_handler |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
accessibility, jsx, reliability |
Description
Reports a mouse or keyboard handler on a JSX element whose tag carries a structural role and which declares no role of its own.
Rationale
Attaching an event handler makes an element behave like a control while its role keeps saying it is content. Nothing tells a screen reader user the element can be activated, and nothing puts it in the tab order, so the behaviour exists only for a pointer: the feature is present for mouse users and absent for everyone navigating by keyboard. The element’s own role is what makes this silent — a list item announced as a list item gives no hint that it does anything.
<li onClick={select}>Details</li> // FLAW - a list item that acts
<img src="x.png" alt="Chart" onClick={zoom} /> // FLAW - same
<h2 onKeyDown={move}>Details</h2> // FLAW - same
<li role="option" tabIndex={0} onClick={select}>...</li> // OK - declared as a control
<button onClick={select}>Details</button> // OK - the element for the job
<li onMouseEnter={preview}>Details</li> // OK - hover is not activation
An element that declares a role is left alone whatever the role says: declaring one is the author
stating the element’s semantics deliberately, and whether that role fits the handler is answered by
javascript.jsx_non_interactive_element_interactive_role and
javascript.jsx_interactive_role_needs_focus. This rule is about the element where nobody declared
anything.
div and span are deliberately not judged — they carry no implicit role, so the mismatch this
rule is named for does not arise, and html.separate_content_presentation is the nearest shipped
rule on that theme. The handlers judged are the pointer and key ones that stand in for activation,
and an element is reported once however many of them it carries.