{"record":{"id":"956a6334b9b28ddb","repo":"oxc-project/oxc","slug":"non-interactive-elements-should-not-be-assigned-in","errorCode":null,"errorMessage":"Non-interactive elements should not be assigned interactive roles.","messagePattern":"Non-interactive elements should not be assigned interactive roles\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/jsx_a11y/no_noninteractive_element_to_interactive_role.rs","lineNumber":24,"sourceCode":"use oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\nuse oxc_str::CompactStr;\nuse rustc_hash::FxHashMap;\nuse schemars::JsonSchema;\nuse serde::Deserialize;\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    globals::HTML_TAG,\n    rule::{DefaultRuleConfig, Rule},\n    utils::{\n        get_element_type, has_jsx_prop_ignore_case, is_interactive_role, is_non_interactive_element,\n    },\n};\n\nfn no_noninteractive_element_to_interactive_role_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Non-interactive elements should not be assigned interactive roles.\")\n        .with_help(\"Remove the interactive role or use an appropriate interactive element instead.\")\n        .with_label(span)\n}\n\n/// Default allowed overrides matching the `eslint-plugin-jsx-a11y` recommended config.\nfn default_allowed_roles() -> FxHashMap<CompactStr, Vec<CompactStr>> {\n    let mut map = FxHashMap::default();\n    map.insert(\n        CompactStr::new(\"ul\"),\n        vec![\n            CompactStr::new(\"menu\"),\n            CompactStr::new(\"menubar\"),\n            CompactStr::new(\"radiogroup\"),\n            CompactStr::new(\"tablist\"),\n            CompactStr::new(\"tree\"),\n            CompactStr::new(\"treegrid\"),\n        ],\n    );","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/jsx_a11y/no_noninteractive_element_to_interactive_role.rs#L6-L42","documentation":"This is the `jsx_a11y/no-noninteractive-element-to-interactive-role` rule in oxlint. It fires when a non-interactive HTML element (per `is_non_interactive_element`) is given an interactive ARIA role (per `is_interactive_role`), e.g. `<ol role=\"listbox\">` or `<table role=\"grid\">`. The mismatch breaks native semantics and expected keyboard behavior that the interactive role promises.","triggerScenarios":"A non-interactive element carries a `role` whose literal value resolves to an interactive role, and the (element, role) pair is not whitelisted. Defaults (mirroring eslint-plugin-jsx-a11y, see `default_allowed_roles`) allow e.g. `ul` -> `menu`/`menubar` and a few others, which the user config can override or extend.","commonSituations":"Building listboxes/menus out of `<ol>`/`<ul>`; converting tables to grids with `role=\"grid\"`; refactors where an element was swapped but the role kept; adopting jsx-a11y recommended config and finding many legacy role overrides.","solutions":["Use the semantically correct native element (`<select>`, `<button>`, real menu markup) instead of a role override.","If the role override is a sanctioned pattern (like `ul` -> `menu`), confirm it is in the allowed mapping or add it to the rule's config.","Restructure so the interactive role lands on an element that also provides full keyboard support."],"exampleFix":"// before\n<ol role=\"listbox\" value={v} onChange={c}>...</ol>\n\n// after\n<select value={v} onChange={c}>...</select>","handlingStrategy":"validation","validationCode":"npx oxlint --jsx-a11y/no-noninteractive-element-to-interactive-role src/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer native interactive elements over role overrides on containers.","If a role override is standard (ul->menu), record it in the allowed-roles config once.","Run oxlint in CI with the nextjs/jsx-a11y presets before role-heavy refactors."],"tags":["jsx-a11y","react","accessibility","aria-roles","lint"],"backgroundTag":"invalid-aria-role-assignment","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}