Non-Interactive Role On An Interactive Element

ID

javascript.jsx_interactive_element_non_interactive_role

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

accessibility, jsx, reliability

Description

Reports a structural ARIA role on a JSX element that is an interactive control.

Rationale

An interactive element keeps its behaviour whatever role it claims: the button is still clickable, the link still navigates, both are still in the tab order. Only the announcement changes, and it changes to something that says the element does nothing. A screen reader user is told this is a heading, or a decoration, and has no reason to activate it — the control becomes invisible while remaining reachable by Tab, which is the worst of both.

<button role="heading" onClick={open}>Details</button>   // FLAW - announced as a heading
<a href="/x" role="presentation">Home</a>                // FLAW - a link with no semantics

<button onClick={open}>Details</button>                  // OK
<button role="tab" onClick={open}>Details</button>       // OK - still a control
<h2><button onClick={open}>Details</button></h2>         // OK - heading around the control
<a role="heading" aria-level="2">Details</a>             // OK - no href, so not a control

role="presentation" and role="none" are the sharpest form of this: they ask for the semantics to be stripped, and on a focusable element the specification says that request is ignored, so the markup states an intent the browser will not honour.

The elements judged are the interactive controls: button, select, textarea, summary and details; a and area when they carry an href; and input of any type but hidden. Roles whose interactivity depends on their container, and group, the implicit role of details, are excluded.

Remediation

Drop the role and let the control’s own semantics stand. Where the structure is genuinely wanted, wrap the control in the structural element instead of relabelling it — a button inside an h2, not a button claiming to be one.

© 2026 Xygeni. All rights reserved