Skip to content

Remove prohibited aria-label from HasMany badge - #2217

Merged
Flo0807 merged 2 commits into
developfrom
fix/has-many-badge-aria-prohibited-attr
Aug 24, 2026
Merged

Remove prohibited aria-label from HasMany badge#2217
Flo0807 merged 2 commits into
developfrom
fix/has-many-badge-aria-prohibited-attr

Conversation

@Flo0807

@Flo0807 Flo0807 commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Problem

CI on #2206 (Update dependency a11y_audit to ~> 0.5.0) fails with one accessibility violation:

1) test posts edit a11y (DemoWeb.Browser.PostBrowserTest)
   Expected page to have no accessibility violations, but got 1 violation.

   serious  Elements must only use permitted ARIA attributes
   https://dequeuniversity.com/rules/axe/4.13/aria-prohibited-attr

   There are 2 nodes with this violation:
   1. <label class="flex cursor-pointer items-center pr-2" for="has-many-tags-checkbox-value-…
        - aria-label attribute cannot be used on a label with no valid role attribute.

a11y_audit 0.5.0 ships a newer axe-core, whose aria-prohibited-attr rule now flags this. The <label> element has no corresponding ARIA role, so aria-label is not allowed on it — and is ignored by assistive technology anyway.

Fix

The offending element is the "x" of a selected badge in Backpex.Fields.HasMany. It is a <label for=…> pointing at the option's checkbox, so clicking it unselects the option.

That label is a pointer-only shortcut: labels are not focusable, so keyboard and screen reader users never reached it. They unselect an option via the checkbox in the dropdown menu instead. So the label is now hidden from assistive technology with aria-hidden="true" rather than given a name it cannot expose.

This has a second benefit: the badges live inside the dropdown trigger, which has role="button" and therefore derives its accessible name from its contents. Previously each badge contributed a duplicated "Unselect " to that name; now the trigger announces just the selected labels.

Alternatives considered:

  • sr-only text inside the label — the label is associated with the checkbox via for, so the text would be appended to the checkbox's accessible name ("Tag Unselect Tag") and to the trigger's.
  • role="button" on the label (as multi_select_badge in Backpex.HTML.Form does on a <div>) — would permit aria-label, but creates a button that is not keyboard focusable, and risks tripping aria-allowed-role.

The "Unselect %{label}" translation is still used by Backpex.HTML.Form.multi_select_badge, where it sits on a <div role="button"> and is permitted, so no gettext changes are needed.

Verification

Run locally against a11y_audit 0.5.0 (the version from #2206):

  • Before: Result: 3/4 passedposts edit a11y fails with the violation above.
  • After: Result: 41 passed, 325 excluded (full --only playwright suite; previously 40/41).

Also green: mix test (158 doctests, 447 tests, 0 failures), mix format, mix credo.

Once this lands, #2206 should go green after a rebase.

axe 4.13 (pulled in by a11y_audit 0.5.0) flags the unselect label of a
selected HasMany badge with `aria-prohibited-attr`: a `<label>` has no
corresponding ARIA role, so `aria-label` is not allowed on it and is
ignored by assistive technology.

The label is a pointer-only shortcut for the checkbox it points to.
Screen reader users unselect an option via that checkbox in the dropdown
menu, so hide the label instead. This also keeps the duplicated text out
of the accessible name of the surrounding dropdown trigger, which is
computed from its contents.
Comment thread lib/backpex/fields/has_many.ex Outdated
@Flo0807 Flo0807 added the bug Something isn't working label Aug 24, 2026
@Flo0807
Flo0807 added this pull request to the merge queue Aug 24, 2026
Merged via the queue into develop with commit 18d6440 Aug 24, 2026
8 checks passed
@Flo0807
Flo0807 deleted the fix/has-many-badge-aria-prohibited-attr branch August 24, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant