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.

Remediation

Use a button for an action and an a with an href for navigation; both come with focus, key handling and the right announcement. Where the tag has to stay, give the element an interactive role, a tabIndex and a keyboard handler alongside the pointer one.

© 2026 Xygeni. All rights reserved