diff --git a/crates/biome_aria/src/roles.rs b/crates/biome_aria/src/roles.rs index b84de06dc6d1..a61799d21056 100644 --- a/crates/biome_aria/src/roles.rs +++ b/crates/biome_aria/src/roles.rs @@ -1174,6 +1174,23 @@ impl<'a> AriaRoles { return false; } + // Allow SVG elements with role="img" attribute + // This is recommended for accessibility purposes + // Example: + // ``` + // ; + // ``` + // For more information, see: + // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/img_role#svg_and_roleimg + if element_name == "svg" + && attributes + .as_ref() + .and_then(|a| a.get("role")) + .map_or(false, |values| values.iter().any(|x| x == "img")) + { + return false; + } + // SVG elements, by default, do not have interactive semantics. // They are primarily used for graphics and visual rendering. While they can be made interactive with additional // attributes and JavaScript, inherently they don't provide user interaction capabilities. diff --git a/crates/biome_js_analyze/src/lint/a11y/no_interactive_element_to_noninteractive_role.rs b/crates/biome_js_analyze/src/lint/a11y/no_interactive_element_to_noninteractive_role.rs index 6682f11aedd1..d20f08d48b4b 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_interactive_element_to_noninteractive_role.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_interactive_element_to_noninteractive_role.rs @@ -73,6 +73,11 @@ impl Rule for NoInteractiveElementToNoninteractiveRole { return None; } + // A element can be given an "img" to make it non-interactive for a11y reasons. + if element_name.text_trimmed() == "svg" && role_attribute_value == "img" { + return None; + } + // A element can be given an "img" to make it non-interactive for a11y reasons. if element_name.text_trimmed() == "canvas" && role_attribute_value == "img" { return None; diff --git a/crates/biome_js_analyze/src/lint/nursery/use_semantic_elements.rs b/crates/biome_js_analyze/src/lint/nursery/use_semantic_elements.rs index 3ef0c86116d0..d69012b27d2b 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_semantic_elements.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_semantic_elements.rs @@ -52,7 +52,7 @@ impl Rule for UseSemanticElements { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - let role_attribute = node.find_attribute_by_name("role").unwrap(); + let role_attribute = node.find_attribute_by_name("role").ok().flatten(); if let Some(attr) = role_attribute { // check is not interactive element diff --git a/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx b/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx index b49a2627f392..7d96747b1eff 100644 --- a/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx +++ b/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx @@ -12,3 +12,6 @@ export const Component2 = () => ( hello world ); + +export const C = +; diff --git a/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx.snap b/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx.snap index 768df524c3ac..e7c75a70afbd 100644 --- a/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx.snap +++ b/crates/biome_js_analyze/tests/specs/nursery/useSemanticElements/valid.jsx.snap @@ -19,4 +19,7 @@ export const Component2 = () => ( ); +export const C = +; + ```