fix(a11y): DisabledLinkRow uses non-semantic aria-disabled on div #1149

Closed
opened 2026-05-14 11:51:37 +00:00 by claude-desktop · 0 comments
Collaborator

As a keyboard/screen-reader user, I want disabled menu items to be semantically correct, so that assistive technology communicates their state accurately.

Location

apps/web/src/components/avatar-menu.tsx:373

DisabledLinkRow renders aria-disabled="true" on a plain <div>. A <div> with aria-disabled is informational only — it does not prevent focus or interaction and is not announced consistently by screen readers.

Acceptance criteria

Fix

  • Replace <div aria-disabled="true"> with either:
    • A <button disabled> styled to look like a list item, or
    • A <div role="listitem" aria-disabled="true"> with tabIndex={-1} and keydown guard
  • Disabled state is announced by VoiceOver / NVDA as "dimmed" or "unavailable"
  • Element is not reachable via Tab when disabled
  • Visual appearance unchanged

Tests

  • Manual keyboard nav: Tab skips the disabled row
  • just qa passes

Out of scope

  • Other a11y issues in avatar-menu (theme radio group uses role="radio" on <button> — already acceptable with existing biome-ignore annotation)
As a keyboard/screen-reader user, I want disabled menu items to be semantically correct, so that assistive technology communicates their state accurately. ## Location `apps/web/src/components/avatar-menu.tsx:373` `DisabledLinkRow` renders `aria-disabled="true"` on a plain `<div>`. A `<div>` with `aria-disabled` is informational only — it does not prevent focus or interaction and is not announced consistently by screen readers. ## Acceptance criteria ### Fix - [ ] Replace `<div aria-disabled="true">` with either: - A `<button disabled>` styled to look like a list item, or - A `<div role="listitem" aria-disabled="true">` with `tabIndex={-1}` and keydown guard - [ ] Disabled state is announced by VoiceOver / NVDA as "dimmed" or "unavailable" - [ ] Element is not reachable via Tab when disabled - [ ] Visual appearance unchanged ### Tests - [ ] Manual keyboard nav: Tab skips the disabled row - [ ] `just qa` passes ## Out of scope - Other a11y issues in avatar-menu (theme radio group uses `role="radio"` on `<button>` — already acceptable with existing `biome-ignore` annotation)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/agent-hooks#1149
No description provided.