oxc-project/oxc · warning
Non-interactive elements should not be assigned mouse or key
Error message
Non-interactive elements should not be assigned mouse or keyboard event listeners.
What it means
This is the `jsx_a11y/no-noninteractive-element-interactions` rule in oxlint. It fires when a non-interactive HTML element (per `is_non_interactive_element`, e.g. `<li>`, `<td>`, `<h1>`) is assigned a mouse or keyboard event handler such as `onClick` or `onKeyDown`. Screen-reader users get no affordance that the element is operable, so handlers belong on interactive elements.
Source
Thrown at crates/oxc_linter/src/rules/jsx_a11y/no_noninteractive_element_interactions.rs:29
use oxc_str::CompactStr;
use rustc_hash::FxHashMap;
use schemars::JsonSchema;
use serde::Deserialize;
use crate::{
AstNode,
context::LintContext,
globals::HTML_TAG,
rule::{DefaultRuleConfig, Rule},
utils::{
get_element_type, get_prop_value, get_string_literal_prop_value, has_jsx_prop,
has_jsx_prop_ignore_case, is_hidden_from_screen_reader, is_interactive_element,
is_interactive_role, is_non_interactive_element, is_non_interactive_role, parse_jsx_value,
},
};
fn no_noninteractive_element_interactions_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(
"Non-interactive elements should not be assigned mouse or keyboard event listeners.",
)
.with_help(
"Move the handler to an interactive element, or use an appropriate interactive role.",
)
.with_label(span)
}
const RECOMMENDED_HANDLERS: &[&str] = &[
// image
"onError",
"onLoad",
// keyboard
"onKeyPress",
"onKeyDown",
"onKeyUp",
// focus
"onFocus",View on GitHub (pinned to e1e7af627c)
Solutions
- Move the handler to a real interactive element such as `<button>` inside the non-interactive one.
- Give the element an interactive role plus `tabIndex` and keyboard handlers (e.g. `role="button" tabIndex={0} onKeyDown={...}`).
- Add the specific handler name to the rule's `handlers` config if it is intentionally non-pointer (like `onMouseOver`).
Example fix
// before
<li onClick={() => select(item)}>{item.name}</li>
// after
<li><button onClick={() => select(item)}>{item.name}</button></li> Defensive patterns
Strategy: validation
Validate before calling
npx oxlint --jsx-a11y/no-noninteractive-element-interactions src/
Prevention
- Default to <button> for anything clickable inside lists/tables/headings.
- Keep intentional exceptions (onError/onLoad on media) in the rule's handler config.
- Add keyboard equivalents whenever you move a handler onto an element.
When it happens
Trigger: A non-interactive HTML element carries a handler prop (via `get_prop_value`) that is not in the allowed `RECOMMENDED_HANDLERS` list (which permits things like `onError`/`onLoad` on images), the element is not hidden from screen readers, has no interactive role, and the pairing is not exempted by the rule's `handlers`/role config.
Common situations: `<li onClick>` in hand-rolled menus and listboxes; `<td onClick>` in clickable table rows; `<h2 onClick>` acting as a disclosure toggle; components built before the team adopted jsx-a11y.
Related errors
- Static HTML elements with event handlers require a role.
- ARIA used where native HTML could suffice.
- Missing `alt` attribute.
- Invalid `alt` value.
- Missing value for `aria-label` attribute.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/d6ce13c3ec678e2c.
Report an issue: GitHub.