react-doctor/no-interactive-element-to-noninteractive-role

Don't override an interactive element's semantics with a non-interactive role.

Validation prompt

Use this to decide whether a fired diagnostic is real or a false positive.

Fires when a natively interactive HTML element carries a string-literal role= whose first token is a non-interactive role or a presentation role (presentation/none): input (every type, even hidden), button, select, textarea, option, menuitem, datalist, audio, video, canvas, embed, summary, td, th, tr, plus a/area with href and img with usemap. Per-tag allowances are skipped (tr permits none/presentation, canvas permits img). False positive: the role value must be a static string literal — dynamic role={expr}, a forwarded {...props}, or a namespaced ns:role is never inspected, so a finding on those is impossible; also note getElementType remaps custom components via jsx-a11y components settings, so a flagged <Link role="img" /> only fires when Link is mapped to an interactive tag.

Fix prompt

Use this once validation confirms the diagnostic is real.

Don't paper over an interactive control with a static role — either drop the conflicting role so the native semantics stand (<button>Save</button> instead of <button role="img">), or if the element is genuinely meant to be non-interactive, swap it for the right non-interactive element (use <div role="img" aria-label="..."> rather than <a href role="img">). Keep interactive roles (button, link, checkbox, etc.) on interactive elements, and reserve role="presentation"/"none" for purely decorative non-interactive tags. See https://oxc.rs/docs/guide/usage/linter/rules/jsx_a11y/no-interactive-element-to-noninteractive-role