diff --git a/.changeset/fix-hr-presentation-role.md b/.changeset/fix-hr-presentation-role.md new file mode 100644 index 000000000000..78749ee9ba26 --- /dev/null +++ b/.changeset/fix-hr-presentation-role.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [#9024](https://github.com/biomejs/biome/issues/9024). The `noInteractiveElementToNoninteractiveRole` rule no longer incorrectly flags `
` elements with `role="presentation"` or `role="none"`. The `separator` role (implicit role of `
`) is now treated as non-interactive, matching the WAI-ARIA spec where a non-focusable separator is a static structural element. diff --git a/crates/biome_aria_metadata/src/lib.rs b/crates/biome_aria_metadata/src/lib.rs index 8f90c609ee7f..69b123839e93 100644 --- a/crates/biome_aria_metadata/src/lib.rs +++ b/crates/biome_aria_metadata/src/lib.rs @@ -160,13 +160,19 @@ impl AriaRole { .find_map(|value| value.parse().ok()) } - /// Returns `true` if the given role inherits of `AriaAbstractRole::Widget` and is not `Self::Progressbar`. + /// Returns `true` if the given role inherits of `AriaAbstractRole::Widget` and is not `Self::Progressbar` or `Self::Separator`. /// /// This corresponds to a role that defines a user interface widget (slider, tree control, ...) pub fn is_interactive(self) -> bool { // `progressbar` inherits of `widget`, but its value is always `readonly`. // So we treat it as a non-interactive role. + // + // `separator` inherits of both `structure` and `widget`, but it is only interactive + // when it is focusable (e.g. has `tabindex` and `aria-valuenow`). + // A non-focusable `separator` (such as `
`) is a static structural element. + // See: https://www.w3.org/TR/wai-aria-1.2/#separator self != Self::Progressbar + && self != Self::Separator && self .inherited_abstract_roles() .contains(&AriaAbstractRole::Widget) diff --git a/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx b/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx index 4fb8419839d3..34a10e8aaaed 100644 --- a/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx +++ b/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx @@ -209,6 +209,8 @@
;
;
; +
; +
; ;
  • ;
  • ; diff --git a/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx.snap b/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx.snap index e33025cb2833..c4ed76c73913 100644 --- a/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx.snap +++ b/crates/biome_js_analyze/tests/specs/a11y/noInteractiveElementToNoninteractiveRole/valid.jsx.snap @@ -215,6 +215,8 @@ expression: valid.jsx
    ;
    ;
    ; +
    ; +
    ; ;
  • ;
  • ;