From c183dcab5c1da7b675b40cb79cc4fbbf22550cbf Mon Sep 17 00:00:00 2001 From: Aviral Dua Date: Sun, 15 Mar 2026 21:11:43 -0700 Subject: [PATCH 1/4] feat(html): port noAriaHiddenOnFocusable a11y rule to HTML Port the noAriaHiddenOnFocusable lint rule from JSX to HTML. The rule enforces that aria-hidden=true is not set on focusable elements. Addresses all review feedback: - Use let-chains for tabindex checking - Return Option from is_focusable_element with ? operator - Business-logic doc comments on all helper functions - Exclude input type=hidden from focusability (HTML spec) - Tighten contenteditable to HTML spec enumerated states: only true/empty/plaintext-only are editing hosts - Case sensitivity tests (BUTTON, INPUT uppercase) - Component tests (MyButton - not flagged) - Framework test coverage: Vue, Svelte, Astro (valid + invalid) - Changeset bumped to minor with example snippet - All snapshots generated via cargo insta - Clippy clean, all 8 tests pass Part of biomejs#8155. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../port-no-aria-hidden-on-focusable-html.md | 13 + .../lint/a11y/no_aria_hidden_on_focusable.rs | 212 +++++++++++ .../astro/invalid.astro | 13 + .../astro/invalid.astro.snap | 272 ++++++++++++++ .../noAriaHiddenOnFocusable/astro/valid.astro | 25 ++ .../astro/valid.astro.snap | 33 ++ .../a11y/noAriaHiddenOnFocusable/invalid.html | 16 + .../noAriaHiddenOnFocusable/invalid.html.snap | 338 ++++++++++++++++++ .../svelte/invalid.svelte | 13 + .../svelte/invalid.svelte.snap | 272 ++++++++++++++ .../svelte/valid.svelte | 25 ++ .../svelte/valid.svelte.snap | 33 ++ .../a11y/noAriaHiddenOnFocusable/valid.html | 17 + .../noAriaHiddenOnFocusable/valid.html.snap | 25 ++ .../noAriaHiddenOnFocusable/vue/invalid.vue | 15 + .../vue/invalid.vue.snap | 276 ++++++++++++++ .../noAriaHiddenOnFocusable/vue/valid.vue | 27 ++ .../vue/valid.vue.snap | 35 ++ 18 files changed, 1660 insertions(+) create mode 100644 .changeset/port-no-aria-hidden-on-focusable-html.md create mode 100644 crates/biome_html_analyze/src/lint/a11y/no_aria_hidden_on_focusable.rs create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/astro/invalid.astro create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/astro/invalid.astro.snap create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/astro/valid.astro create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/astro/valid.astro.snap create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/invalid.html create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/invalid.html.snap create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/svelte/invalid.svelte create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/svelte/invalid.svelte.snap create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/svelte/valid.svelte create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/svelte/valid.svelte.snap create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/valid.html create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/valid.html.snap create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/vue/invalid.vue create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/vue/invalid.vue.snap create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/vue/valid.vue create mode 100644 crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/vue/valid.vue.snap diff --git a/.changeset/port-no-aria-hidden-on-focusable-html.md b/.changeset/port-no-aria-hidden-on-focusable-html.md new file mode 100644 index 000000000000..6a364fd31480 --- /dev/null +++ b/.changeset/port-no-aria-hidden-on-focusable-html.md @@ -0,0 +1,13 @@ +--- +"@biomejs/biome": minor +--- + +Added HTML support for the [`noAriaHiddenOnFocusable`](https://biomejs.dev/linter/rules/no-aria-hidden-on-focusable/) accessibility lint rule, which enforces that `aria-hidden="true"` is not set on focusable elements. Focusable elements include native interactive elements (` + + + + + + + + + + + + +``` + +# Diagnostics +``` +invalid.astro:2:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 1 │ + > 2 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 │ + 4 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 2 │ Click·me + │ ------------------ + +``` + +``` +invalid.astro:3:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 1 │ + 2 │ + > 3 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 4 │ + 5 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 3 │ link + │ ------------------ + +``` + +``` +invalid.astro:4:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 2 │ + 3 │ + > 4 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 5 │ + 6 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 4 │ + │ ------------------- + +``` + +``` +invalid.astro:5:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 3 │ + 4 │ + > 5 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 6 │ + 7 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 5 │ + │ ------------------ + +``` + +``` +invalid.astro:6:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 4 │ + 5 │ + > 6 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 7 │ + 8 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 6 │ + │ ------------------ + +``` + +``` +invalid.astro:7:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 5 │ + 6 │ + > 7 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 8 │ + 9 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 7 │ text + │ ------------------ + +``` + +``` +invalid.astro:8:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 6 │ + 7 │ + > 8 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 9 │ + 10 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 8 │ editable + │ ------------------ + +``` + +``` +invalid.astro:9:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 7 │ + 8 │ + > 9 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 10 │ + 11 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 9 │ editable·bare·attr + │ ------------------ + +``` + +``` +invalid.astro:10:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 8 │ + 9 │ + > 10 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 11 │ + 12 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 10 │ editable·empty·string + │ ------------------ + +``` + +``` +invalid.astro:11:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 9 │ + 10 │ + > 11 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 12 │ + 13 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 11 │ + │ ------------------- + +``` + +``` +invalid.astro:12:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 10 │ + 11 │ + > 12 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 13 │ + 14 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 12 │ details + │ ------------------ + +``` + +``` +invalid.astro:13:1 lint/a11y/noAriaHiddenOnFocusable FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Disallow aria-hidden="true" from being set on focusable elements. + + 11 │ + 12 │ + > 13 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 14 │ + + i aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users. + + i Unsafe fix: Remove the aria-hidden attribute from the element. + + 13 │ summary + │ ------------------ + +``` diff --git a/crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/astro/valid.astro b/crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/astro/valid.astro new file mode 100644 index 000000000000..4b466e0b46e1 --- /dev/null +++ b/crates/biome_html_analyze/tests/specs/a11y/noAriaHiddenOnFocusable/astro/valid.astro @@ -0,0 +1,25 @@ + + + + +