feat(html_analyze): implement noNoninteractiveElementInteractions#10026
Conversation
🦋 Changeset detectedLatest commit: 585fb00 The changes in this PR will be included in the next version bump. This PR includes changesets to release 14 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughAdds a new HTML accessibility lint rule Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
crates/biome_html_analyze/src/a11y.rs (1)
186-195: Consider case-insensitive matching forcontenteditable.HTML attribute values are case-insensitive per spec.
contenteditable="TRUE"orcontenteditable="True"would currently returnfalse. Consider usingeq_ignore_ascii_case("true")for consistency with how other HTML attribute checks work in this module (e.g.,attribute_value_equals_ignore_case).That said, if you're intentionally mirroring the eslint-plugin-jsx-a11y behaviour exactly, this is fine as-is.
🔧 Optional fix for case-insensitivity
pub(crate) fn is_content_editable(element: &AnyHtmlTagElement) -> bool { element .find_attribute_by_name("contenteditable") - .is_some_and(|attribute| is_strict_true_value(&attribute)) + .is_some_and(|attribute| attribute_value_equals_ignore_case(&attribute, "true")) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_html_analyze/src/a11y.rs` around lines 186 - 195, The is_content_editable function currently treats the contenteditable attribute value case-sensitively; update its check in is_content_editable (which takes &AnyHtmlTagElement) to perform a case-insensitive comparison (e.g., use attribute_value_equals_ignore_case or call eq_ignore_ascii_case("true") on the attribute value) so that values like "TRUE" or "True" return true; ensure you still handle the attribute absence the same way (is_some_and(...)).crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue (1)
1-44: Consider adding acontenteditable="true"test case.The
is_content_editablehelper suppresses diagnostics for content-editable elements, but there's no valid test case demonstrating this. Adding one would improve coverage:<div contenteditable="true" `@click`="() => { }"></div>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue` around lines 1 - 44, Add a valid test case demonstrating suppression for content-editable elements by inserting a line with a contenteditable element (e.g. <div contenteditable="true" `@click`="() => { }"></div>) into the existing valid.vue tests so the is_content_editable branch is covered; place it near the other valid div examples (e.g. alongside the presentation/aria-hidden cases) to ensure the rule recognizes contenteditable elements as non-diagnostic.crates/biome_html_syntax/src/element_ext.rs (1)
461-470: Tiny comment fix: directive syntax labels are swapped.
VueVOnShorthandDirectiveis@name, andVueDirectivehere isv-on:name(not:name/v-bind:name).Suggested comment-only patch
- // :name="..." + // `@name`="..." AnyVueDirective::VueVOnShorthandDirective(d) => d @@ - // v-bind:name="..." + // v-on:name="..." AnyVueDirective::VueDirective(d) => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_html_syntax/src/element_ext.rs` around lines 461 - 470, The inline comments labeling directive variants are swapped: update the comment above AnyVueDirective::VueVOnShorthandDirective to indicate it matches the v-on shorthand (e.g., "@name") and change the comment above AnyVueDirective::VueDirective to indicate it matches the full v-on form (e.g., "v-on:name"); locate the matching match arm code around VueVOnShorthandDirective and VueDirective in element_ext.rs and replace the incorrect ":name=\"...\" / v-bind:name=\"...\"" comments with the correct "@name" and "v-on:name" labels respectively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`:
- Around line 15-17: The documentation comment in
no_noninteractive_element_interactions.rs incorrectly lists `<area>` as a
non-interactive element; update the doc comment (the triple-slash block above
the lint implementation in the no_noninteractive_element_interactions module) to
remove `<area>` from the example list so it matches the rule's fixtures and
behavior for allowed elements.
---
Nitpick comments:
In `@crates/biome_html_analyze/src/a11y.rs`:
- Around line 186-195: The is_content_editable function currently treats the
contenteditable attribute value case-sensitively; update its check in
is_content_editable (which takes &AnyHtmlTagElement) to perform a
case-insensitive comparison (e.g., use attribute_value_equals_ignore_case or
call eq_ignore_ascii_case("true") on the attribute value) so that values like
"TRUE" or "True" return true; ensure you still handle the attribute absence the
same way (is_some_and(...)).
In
`@crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue`:
- Around line 1-44: Add a valid test case demonstrating suppression for
content-editable elements by inserting a line with a contenteditable element
(e.g. <div contenteditable="true" `@click`="() => { }"></div>) into the existing
valid.vue tests so the is_content_editable branch is covered; place it near the
other valid div examples (e.g. alongside the presentation/aria-hidden cases) to
ensure the rule recognizes contenteditable elements as non-diagnostic.
In `@crates/biome_html_syntax/src/element_ext.rs`:
- Around line 461-470: The inline comments labeling directive variants are
swapped: update the comment above AnyVueDirective::VueVOnShorthandDirective to
indicate it matches the v-on shorthand (e.g., "@name") and change the comment
above AnyVueDirective::VueDirective to indicate it matches the full v-on form
(e.g., "v-on:name"); locate the matching match arm code around
VueVOnShorthandDirective and VueDirective in element_ext.rs and replace the
incorrect ":name=\"...\" / v-bind:name=\"...\"" comments with the correct
"@name" and "v-on:name" labels respectively.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ac2ea570-a1c5-44d2-8464-e6412b0f3f55
⛔ Files ignored due to path filters (8)
crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/valid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vue.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (13)
.changeset/wicked-lions-brake.mdcrates/biome_html_analyze/src/a11y.rscrates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rscrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astrocrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astrocrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.htmlcrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.sveltecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.sveltecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/valid.htmlcrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vuecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vuecrates/biome_html_syntax/src/element_ext.rscrates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
Merging this PR will degrade performance by 21%
Performance Changes
Comparing Footnotes
|
e1280d3 to
03c2def
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/biome_html_syntax/src/element_ext.rs`:
- Around line 461-470: Update the two inline comments that are copy-pasted
incorrectly: where the match arm for AnyVueDirective::VueVOnShorthandDirective
currently has a comment saying `:name="..."` change it to `@name="..."`, and
where the match arm for AnyVueDirective::VueDirective (handling v-on style
directives) currently has a comment saying `v-bind:name="..."` change it to
`v-on:name="..."`; these comments are adjacent to the VueVOnShorthandDirective
and VueDirective match arms in element_ext.rs and should reflect event-handling
directives.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7d3be585-0c3b-495b-a683-a2f2d9cc6856
⛔ Files ignored due to path filters (8)
crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/valid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vue.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (15)
.changeset/major-bats-fail.md.changeset/wicked-lions-brake.mdcrates/biome_html_analyze/src/a11y.rscrates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rscrates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_to_interactive_role.rscrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astrocrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astrocrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.htmlcrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.sveltecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.sveltecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/valid.htmlcrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vuecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vuecrates/biome_html_syntax/src/element_ext.rscrates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
✅ Files skipped from review due to trivial changes (6)
- .changeset/major-bats-fail.md
- .changeset/wicked-lions-brake.md
- crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_to_interactive_role.rs
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astro
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.svelte
🚧 Files skipped from review as they are similar to previous changes (5)
- crates/biome_html_analyze/src/a11y.rs
- crates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astro
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vue
- crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
03c2def to
030207d
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`:
- Around line 122-124: The diagnostic note string inside the .note(markup! { ...
}) in no_noninteractive_element_interactions.rs has awkward grammar; update the
message to read "Consider replacing with a semantically interactive element like
"<Emphasis>"<button/>"</Emphasis>" or "<Emphasis>"<a href/>"</Emphasis>"."
Locate the .note(markup! { ... }) call that currently contains "Consider replace
semantically interactive element like ..." and replace that fragment with the
corrected "Consider replacing with a semantically interactive element like ..."
text.
- Around line 129-155: The INTERACTIVE_HANDLERS constant contains an invalid
HTML event name "ondoubleclick" that should be removed; update the slice in
no_noninteractive_element_interactions.rs to delete the "ondoubleclick" entry
(leave "ondblclick" intact) and run tests, and optionally consider whether to
separately add pointer/touch events in a different change if you intend to
support modern input handlers rather than developer-typo checks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7f5767dc-b4f4-460f-86ad-dcd507b291eb
⛔ Files ignored due to path filters (8)
crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/valid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vue.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (15)
.changeset/major-bats-fail.md.changeset/wicked-lions-brake.mdcrates/biome_html_analyze/src/a11y.rscrates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rscrates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_to_interactive_role.rscrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astrocrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astrocrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.htmlcrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.sveltecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.sveltecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/valid.htmlcrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vuecrates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vuecrates/biome_html_syntax/src/element_ext.rscrates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
✅ Files skipped from review due to trivial changes (8)
- .changeset/major-bats-fail.md
- .changeset/wicked-lions-brake.md
- crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_to_interactive_role.rs
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vue
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/valid.astro
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/valid.vue
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/valid.svelte
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astro
🚧 Files skipped from review as they are similar to previous changes (4)
- crates/biome_html_analyze/src/a11y.rs
- crates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
- crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.svelte
- crates/biome_html_syntax/src/element_ext.rs
| .note(markup! { | ||
| "Consider replace semantically interactive element like "<Emphasis>"<button/>"</Emphasis>" or "<Emphasis>"<a href/>"</Emphasis>"." | ||
| }) |
There was a problem hiding this comment.
Minor grammar tweak in diagnostic message.
The note reads "Consider replace semantically" — should be "Consider replacing with a semantically".
Suggested fix
.note(markup! {
- "Consider replace semantically interactive element like "<Emphasis>"<button/>"</Emphasis>" or "<Emphasis>"<a href/>"</Emphasis>"."
+ "Consider replacing with a semantically interactive element like "<Emphasis>"<button/>"</Emphasis>" or "<Emphasis>"<a href/>"</Emphasis>"."
})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .note(markup! { | |
| "Consider replace semantically interactive element like "<Emphasis>"<button/>"</Emphasis>" or "<Emphasis>"<a href/>"</Emphasis>"." | |
| }) | |
| .note(markup! { | |
| "Consider replacing with a semantically interactive element like "<Emphasis>"<button/>"</Emphasis>" or "<Emphasis>"<a href/>"</Emphasis>"." | |
| }) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`
around lines 122 - 124, The diagnostic note string inside the .note(markup! {
... }) in no_noninteractive_element_interactions.rs has awkward grammar; update
the message to read "Consider replacing with a semantically interactive element
like "<Emphasis>"<button/>"</Emphasis>" or "<Emphasis>"<a href/>"</Emphasis>"."
Locate the .note(markup! { ... }) call that currently contains "Consider replace
semantically interactive element like ..." and replace that fragment with the
corrected "Consider replacing with a semantically interactive element like ..."
text.
| const INTERACTIVE_HANDLERS: &[&str] = &[ | ||
| "onclick", | ||
| "oncontextmenu", | ||
| "ondblclick", | ||
| "ondoubleclick", | ||
| "ondrag", | ||
| "ondragend", | ||
| "ondragenter", | ||
| "ondragexit", | ||
| "ondragleave", | ||
| "ondragover", | ||
| "ondragstart", | ||
| "ondrop", | ||
| "onmousedown", | ||
| "onmouseenter", | ||
| "onmouseleave", | ||
| "onmousemove", | ||
| "onmouseout", | ||
| "onmouseover", | ||
| "onkeydown", | ||
| "onkeypress", | ||
| "onkeyup", | ||
| "onfocus", | ||
| "onblur", | ||
| "onload", | ||
| "onerror", | ||
| ]; |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
What are all the standard HTML global event handler attributes?
💡 Result:
The standard HTML global event handler attributes are those available on all HTML elements as content attributes (and IDL attributes on elements, Document, and Window). They correspond to common DOM events and are prefixed with "on". According to MDN Web Docs (the most comprehensive and up-to-date list from authoritative sources tracking the HTML Living Standard), they include: onabort, onanimationcancel, onanimationend, onanimationiteration, onanimationstart, onauxclick, onbeforeinput, onbeforematch, onbeforetoggle, onblur, oncancel, oncanplay, oncanplaythrough, onchange, onclick, onclose, oncommand, oncontentvisibilityautostatechange, oncontextlost, oncontextmenu, oncontextrestored, oncopy, oncuechange, oncut, ondblclick, ondrag, ondragend, ondragenter, ondragleave, ondragover, ondragstart, ondrop, ondurationchange, onemptied, onended, onerror, onfocus, onfocusin, onfocusout, onformdata, onfullscreenchange, onfullscreenerror, ongesturechange, ongestureend, ongesturestart, ongotpointercapture, oninput, oninvalid, onkeydown, onkeypress, onkeyup, onload, onloadeddata, onloadedmetadata, onloadstart, onlostpointercapture, onmousedown, onmouseenter, onmouseleave, onmousemove, onmouseout, onmouseover, onmouseup, onmousewheel, onpaste, onpause, onplay, onplaying, onpointercancel, onpointerdown, onpointerenter, onpointerleave, onpointermove, onpointerout, onpointerover, onpointerrawupdate, onpointerup, onprogress, onratechange, onreset, onresize, onscroll, onsecuritypolicyviolation, onseeked, onseeking, onselect, onselectionchange, onselectstart, onslotchange, onstalled, onsubmit, onsuspend, ontimeupdate, ontoggle, onvolumechange, onwaiting, onwebkitanimationend, onwebkitanimationiteration, onwebkitanimationstart, onwebkittransitionend, onwheel, onwebkitmouseforcedown, onwebkitmouseforceup, onwebkitmouseforcewillbegin. The WHATWG HTML Living Standard (section 8.1.6.2) confirms these are the event handlers supported by all HTML elements as content attributes, with some additional Window-specific ones on body/frameset. MDN's list reflects the current standard as of 2026, including newer events like onbeforetoggle and oncontentvisibilityautostatechange. Note: While all "on*" attributes for known events are accepted on elements, only those corresponding to events that can fire on arbitrary elements are truly "global" in effect. Vendor-prefixed (webkit*) and deprecated (onkeypress) ones are included for completeness as they are standard global attributes.
Citations:
- 1: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes
- 2: https://html.spec.whatwg.org/dev/webappapis.html
- 3: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/
- 4: https://html.spec.whatwg.org/multipage/indices.html
- 5: https://www.whatwg.org/specs/web-apps/current-work/complete/indices.html
🏁 Script executed:
# First, let's understand the rule's purpose
cat -n crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs | head -150Repository: biomejs/biome
Length of output: 6326
🏁 Script executed:
# Check if there are any comments or rationale around INTERACTIVE_HANDLERS
rg -A 5 -B 5 "INTERACTIVE_HANDLERS" crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rsRepository: biomejs/biome
Length of output: 564
🏁 Script executed:
# Look for test files related to this rule
fd "no_noninteractive_element_interactions" crates/biome_html_analyze/tests/Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Look for test files related to this rule
find crates/biome_html_analyze/tests -name "*no_noninteractive*" -type fRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check if there are snapshot tests or fixtures
find crates/biome_html_analyze/tests -type d -name "no_noninteractive*"Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Search for any discussion or comments about ondoubleclick in the codebase
rg "ondoubleclick" --type-add "rust:*.rs" -B 3 -A 3Repository: biomejs/biome
Length of output: 755
🏁 Script executed:
# Check git history or comments about why ondoubleclick might be there
rg "doubleclick" crates/ --type-add "rust:*.rs" -B 2 -A 2Repository: biomejs/biome
Length of output: 557
🏁 Script executed:
# Check if there are similar rules in other linters (JS/TS)
find crates -name "*noninteractive*" -type f | head -20Repository: biomejs/biome
Length of output: 909
🏁 Script executed:
# Look for any configuration or documentation about this rule
find . -name "*.md" -o -name "*.json" | xargs grep -l "noNoninteractiveElementInteractions" 2>/dev/null | head -5Repository: biomejs/biome
Length of output: 143
🏁 Script executed:
# Check if the rule was recently added or modified with any commit message context
git log --oneline -n 50 -- crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs 2>/dev/null | head -10Repository: biomejs/biome
Length of output: 132
🏁 Script executed:
# Check ESLint jsx-a11y plugin (often the source of accessibility rules) for comparison
# This will help understand if ondoubleclick is intentional
rg "ondoubleclick|onTouchStart|ontouchstart" --type-add "rust:*.rs" --type-add "ts:*.ts" --type-add "js:*.js" crates/ | head -20Repository: biomejs/biome
Length of output: 1093
🏁 Script executed:
# Check the JS version of the same rule to see if it has different handlers
cat crates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs | grep -A 30 "INTERACTIVE_HANDLERS"Repository: biomejs/biome
Length of output: 758
🏁 Script executed:
# Look for test specs for the HTML rule
find crates/biome_html_analyze/tests/specs -name "*noNoninteractive*" -o -name "*interactive*" | head -10Repository: biomejs/biome
Length of output: 287
🏁 Script executed:
# Check the test specs for the HTML rule to understand intended behavior
ls -la crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/Repository: biomejs/biome
Length of output: 604
🏁 Script executed:
# Read the test files to see if ondoubleclick is actually tested
cat crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/*.html 2>/dev/null | head -100Repository: biomejs/biome
Length of output: 3981
🏁 Script executed:
# Check if there's a snapshot file
cat crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/*.snap 2>/dev/null | head -150Repository: biomejs/biome
Length of output: 5357
🏁 Script executed:
# Let's check if this mirrors ESLint's jsx-a11y rule by searching online documentation
# First, check the original source attribution in comments or changelog
git log --all --format="%B" -n 20 | grep -i "noninteractive\|jsx-a11y\|eslint" | head -20Repository: biomejs/biome
Length of output: 122
🏁 Script executed:
# Check if there's any Svelte-specific event handling mentioned
rg "svelte\|Svelte" crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs -B 5 -A 5Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Look at the Svelte test directory to see if ondoubleclick is tested there
cat crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/*.html 2>/dev/nullRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Let me check if there's any ESLint jsx-a11y documentation referenced
rg "jsx-a11y\|eslint" crates/biome_html_analyze/src/lint/a11y/ -lRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check the rule options to see if there's any configuration
cat crates/biome_rule_options/src/no_noninteractive_element_interactions.rsRepository: biomejs/biome
Length of output: 427
🏁 Script executed:
# Let's verify what pointer events are in the standard
# and whether they should be included instead of touch events
rg "onpointer" crates/biome_html_analyze/src/lint/a11y/ -lRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check if there are any other HTML event handlers we're missing
cat crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs | tail -20Repository: biomejs/biome
Length of output: 558
Remove ondoubleclick — it's not a valid HTML event attribute.
The standard attribute is ondblclick (already present on line 131). ondoubleclick won't trigger any browser behaviour and will only cause confusion. If you're trying to catch developer typos, that logic belongs in a different linter rule, not in an accessibility rule that checks for actual event handlers.
Touch events (ontouchstart, ontouchend, etc.) are notably absent, though they're widely used. The modern standard uses pointer events (onpointerdown, onpointerup, etc.) instead, which are also missing. Worth considering whether this list is intentionally scoped to just mouse/keyboard, or if it needs updating for modern input handling.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`
around lines 129 - 155, The INTERACTIVE_HANDLERS constant contains an invalid
HTML event name "ondoubleclick" that should be removed; update the slice in
no_noninteractive_element_interactions.rs to delete the "ondoubleclick" entry
(leave "ondblclick" intact) and run tests, and optionally consider whether to
separately add pointer/touch events in a different change if you intend to
support modern input handlers rather than developer-typo checks.
There was a problem hiding this comment.
Neither in the JS rule, not sure why those are missing 🤔
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`:
- Around line 69-74: The rule metadata for NoNoninteractiveElementInteractions
is missing a sources mapping; add a sources entry that mirrors the upstream JS
variant so migration and codegen can map back to ESLint. Update the
NoNoninteractiveElementInteractions metadata to include sources:
vec![RuleSource::Eslint("no-noninteractive-element-interactions").same()] (using
RuleSource::Eslint and the same() helper) to match the ESLint rule name and
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4eff7d9a-d27e-4125-a633-16b0607306f6
📒 Files selected for processing (1)
crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
| pub NoNoninteractiveElementInteractions { | ||
| version: "next", | ||
| name: "noNoninteractiveElementInteractions", | ||
| language: "html", | ||
| recommended: false, | ||
| } |
There was a problem hiding this comment.
Carry over the upstream sources mapping.
This is a straight port, but the rule metadata has no sources entry. That leaves generated rule metadata and biome migrate eslint with nothing to map back to the upstream rule. Please mirror the source annotation used by the JS variant here.
Based on learnings, Use RuleSource::Eslint("rule-name").same() when porting an ESLint rule with matching behavior, and RuleSource metadata affects codegen and biome migrate eslint detection.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`
around lines 69 - 74, The rule metadata for NoNoninteractiveElementInteractions
is missing a sources mapping; add a sources entry that mirrors the upstream JS
variant so migration and codegen can map back to ESLint. Update the
NoNoninteractiveElementInteractions metadata to include sources:
vec![RuleSource::Eslint("no-noninteractive-element-interactions").same()] (using
RuleSource::Eslint and the same() helper) to match the ESLint rule name and
behavior.
Summary
Port
noNoninteractiveElementInteractionsto the HTML analyzerRelated #8155
Test Plan
Added unit tests
Docs