diff --git a/crates/biome_js_analyze/src/aria_analyzers/a11y/no_redundant_roles.rs b/crates/biome_js_analyze/src/aria_analyzers/a11y/no_redundant_roles.rs
index 6de14c16c3b4..50adf2e112fe 100644
--- a/crates/biome_js_analyze/src/aria_analyzers/a11y/no_redundant_roles.rs
+++ b/crates/biome_js_analyze/src/aria_analyzers/a11y/no_redundant_roles.rs
@@ -94,7 +94,7 @@ impl Rule for NoRedundantRoles {
rule_category!(),
state.redundant_attribute_value.range(),
markup! {
- "Using the role attribute '"{role_attribute}"' on the '"{element}"' element is redundant."
+ "Using the role attribute '"{role_attribute}"' on the '"{element}"' element is redundant, because it is implied by the semantic '"{element}"' element."
},
))
}
diff --git a/crates/biome_js_analyze/tests/specs/a11y/noRedundantRoles/invalid.jsx.snap b/crates/biome_js_analyze/tests/specs/a11y/noRedundantRoles/invalid.jsx.snap
index aacb0c0580ef..67c2bd56ee1a 100644
--- a/crates/biome_js_analyze/tests/specs/a11y/noRedundantRoles/invalid.jsx.snap
+++ b/crates/biome_js_analyze/tests/specs/a11y/noRedundantRoles/invalid.jsx.snap
@@ -45,7 +45,7 @@ expression: invalid.jsx
```
invalid.jsx:2:16 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'article' on the 'article' element is redundant.
+ ! Using the role attribute 'article' on the 'article' element is redundant, because it is implied by the semantic 'article' element.
1 │ <>
> 2 │
@@ -63,7 +63,7 @@ invalid.jsx:2:16 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:3:15 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'button' on the 'button' element is redundant.
+ ! Using the role attribute 'button' on the 'button' element is redundant, because it is implied by the semantic 'button' element.
1 │ <>
2 │
@@ -82,7 +82,7 @@ invalid.jsx:3:15 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:4:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'heading' on the 'h1' element is redundant.
+ ! Using the role attribute 'heading' on the 'h1' element is redundant, because it is implied by the semantic 'h1' element.
2 │
3 │
@@ -101,7 +101,7 @@ invalid.jsx:4:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:7:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'heading' on the 'h1' element is redundant.
+ ! Using the role attribute 'heading' on the 'h1' element is redundant, because it is implied by the semantic 'h1' element.
5 │ title
6 │
@@ -120,7 +120,7 @@ invalid.jsx:7:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:8:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'heading' on the 'h2' element is redundant.
+ ! Using the role attribute 'heading' on the 'h2' element is redundant, because it is implied by the semantic 'h2' element.
6 │
7 │
title
@@ -139,7 +139,7 @@ invalid.jsx:8:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:9:15 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'dialog' on the 'dialog' element is redundant.
+ ! Using the role attribute 'dialog' on the 'dialog' element is redundant, because it is implied by the semantic 'dialog' element.
7 │
title
8 │
@@ -158,7 +158,7 @@ invalid.jsx:9:15 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:10:30 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'checkbox' on the 'input' element is redundant.
+ ! Using the role attribute 'checkbox' on the 'input' element is redundant, because it is implied by the semantic 'input' element.
8 │
9 │
@@ -177,7 +177,7 @@ invalid.jsx:10:30 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:11:15 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'figure' on the 'figure' element is redundant.
+ ! Using the role attribute 'figure' on the 'figure' element is redundant, because it is implied by the semantic 'figure' element.
9 │
10 │
@@ -196,7 +196,7 @@ invalid.jsx:11:15 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:12:13 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'form' on the 'form' element is redundant.
+ ! Using the role attribute 'form' on the 'form' element is redundant, because it is implied by the semantic 'form' element.
10 │
11 │
@@ -215,7 +215,7 @@ invalid.jsx:12:13 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:14:17 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'group' on the 'fieldset' element is redundant.
+ ! Using the role attribute 'group' on the 'fieldset' element is redundant, because it is implied by the semantic 'fieldset' element.
12 │
13 │ {/* Needs to check the ancestors:
*/}
@@ -234,7 +234,7 @@ invalid.jsx:14:17 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:15:32 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'img' on the 'img' element is redundant.
+ ! Using the role attribute 'img' on the 'img' element is redundant, because it is implied by the semantic 'img' element.
13 │ {/* Needs to check the ancestors:
*/}
14 │
@@ -253,7 +253,7 @@ invalid.jsx:15:32 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:16:19 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'presentation' on the 'img' element is redundant.
+ ! Using the role attribute 'presentation' on the 'img' element is redundant, because it is implied by the semantic 'img' element.
14 │
15 │
@@ -272,7 +272,7 @@ invalid.jsx:16:19 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:17:19 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'link' on the 'a' element is redundant.
+ ! Using the role attribute 'link' on the 'a' element is redundant, because it is implied by the semantic 'a' element.
15 │
16 │
@@ -291,7 +291,7 @@ invalid.jsx:17:19 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:18:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'list' on the 'ol' element is redundant.
+ ! Using the role attribute 'list' on the 'ol' element is redundant, because it is implied by the semantic 'ol' element.
16 │
17 │
@@ -310,7 +310,7 @@ invalid.jsx:18:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:19:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'list' on the 'ul' element is redundant.
+ ! Using the role attribute 'list' on the 'ul' element is redundant, because it is implied by the semantic 'ul' element.
17 │
18 │
@@ -329,7 +329,7 @@ invalid.jsx:19:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:20:27 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'combobox' on the 'select' element is redundant.
+ ! Using the role attribute 'combobox' on the 'select' element is redundant, because it is implied by the semantic 'select' element.
18 │
19 │
@@ -348,7 +348,7 @@ invalid.jsx:20:27 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:21:45 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'listbox' on the 'select' element is redundant.
+ ! Using the role attribute 'listbox' on the 'select' element is redundant, because it is implied by the semantic 'select' element.
19 │
20 │
@@ -367,7 +367,7 @@ invalid.jsx:21:45 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:22:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'listitem' on the 'li' element is redundant.
+ ! Using the role attribute 'listitem' on the 'li' element is redundant, because it is implied by the semantic 'li' element.
20 │
21 │
@@ -386,7 +386,7 @@ invalid.jsx:22:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:23:12 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'navigation' on the 'nav' element is redundant.
+ ! Using the role attribute 'navigation' on the 'nav' element is redundant, because it is implied by the semantic 'nav' element.
21 │
22 │
@@ -405,7 +405,7 @@ invalid.jsx:23:12 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:25:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'row' on the 'tr' element is redundant.
+ ! Using the role attribute 'row' on the 'tr' element is redundant, because it is implied by the semantic 'tr' element.
23 │
24 │ {/* Needs to check the ancestors: */}
@@ -424,7 +424,7 @@ invalid.jsx:25:11 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:26:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'rowgroup' on the 'tbody' element is redundant.
+ ! Using the role attribute 'rowgroup' on the 'tbody' element is redundant, because it is implied by the semantic 'tbody' element.
24 │ {/* Needs to check the ancestors: */}
25 │
@@ -443,7 +443,7 @@ invalid.jsx:26:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:27:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'rowgroup' on the 'tfoot' element is redundant.
+ ! Using the role attribute 'rowgroup' on the 'tfoot' element is redundant, because it is implied by the semantic 'tfoot' element.
25 │
26 │
@@ -462,7 +462,7 @@ invalid.jsx:27:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:28:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'rowgroup' on the 'thead' element is redundant.
+ ! Using the role attribute 'rowgroup' on the 'thead' element is redundant, because it is implied by the semantic 'thead' element.
26 │
27 │
@@ -481,7 +481,7 @@ invalid.jsx:28:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:30:28 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'searchbox' on the 'input' element is redundant.
+ ! Using the role attribute 'searchbox' on the 'input' element is redundant, because it is implied by the semantic 'input' element.
28 │
29 │ {/* Needs to check the ancestors:
*/}
@@ -500,7 +500,7 @@ invalid.jsx:30:28 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:31:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'table' on the 'table' element is redundant.
+ ! Using the role attribute 'table' on the 'table' element is redundant, because it is implied by the semantic 'table' element.
29 │ {/* Needs to check the ancestors:
*/}
30 │
@@ -519,7 +519,7 @@ invalid.jsx:31:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:32:17 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'textbox' on the 'textarea' element is redundant.
+ ! Using the role attribute 'textbox' on the 'textarea' element is redundant, because it is implied by the semantic 'textarea' element.
30 │
31 │
@@ -538,7 +538,7 @@ invalid.jsx:32:17 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━
```
invalid.jsx:33:26 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- ! Using the role attribute 'textbox' on the 'input' element is redundant.
+ ! Using the role attribute 'textbox' on the 'input' element is redundant, because it is implied by the semantic 'input' element.
31 │
a11y/noRedundantRoles.js:1:15 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-✖Using the role attribute 'article' on the 'article' element is redundant.
+✖Using the role attribute 'article' on the 'article' element is redundant, because it is implied by the semantic 'article' element.>1 │ <article role='article'></article>
│ ^^^^^^^^^
@@ -40,7 +40,7 @@ ESLint (eslint-plugin-jsx-a11y) Equivalent: [no-redundant-roles](https://github.
a11y/noRedundantRoles.js:1:14 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-✖Using the role attribute 'button' on the 'button' element is redundant.
+✖Using the role attribute 'button' on the 'button' element is redundant, because it is implied by the semantic 'button' element.>1 │ <button role='button'></button>
│ ^^^^^^^^
@@ -58,7 +58,7 @@ ESLint (eslint-plugin-jsx-a11y) Equivalent: [no-redundant-roles](https://github.
a11y/noRedundantRoles.js:1:10 lint/a11y/noRedundantRoles FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-✖Using the role attribute 'heading' on the 'h1' element is redundant.
+✖Using the role attribute 'heading' on the 'h1' element is redundant, because it is implied by the semantic 'h1' element.>1 │ <h1 role='heading' aria-level='1'>title</h1>
│ ^^^^^^^^^