Skip to content

Modal card and header icon buttons have no accessible name (still present in 1.8.23, follow-up to #2698) #5761

Description

@owenpkent

Both defects reported in #2698 are still present in @reown/appkit 1.8.23
(current npm) and on main. That issue was closed in January 2025 against a
private ticket with no linked fix and is now locked, so this is filed
separately. Checked against the shipped source:

1. The modal card has no accessible name (aria-dialog-name).

packages/scaffold-ui/src/modal/w3m-modal/index.ts, the contentTemplate()
method (around line 150 on main):

<wui-card
  shake="${this.shake}"
  data-embedded="${ifDefined(this.enableEmbedded)}"
  role="alertdialog"
  aria-modal="true"
  tabindex="0"
  data-testid="w3m-modal-card"
>

No aria-label and no aria-labelledby. This is the element
data-testid="w3m-modal-card", present in every modal state: the default
connect view, the account view, the activity tab, and the wrong-network
screen. axe reports aria-dialog-name on it in all of them.

2. The header's help and close icon buttons have no accessible name
(button-name).

Same file area, packages/scaffold-ui/src/partials/w3m-header/index.ts:

  • closeButtonTemplate(), around line 213-222:
    <wui-icon-button
      icon="close"
      size="lg"
      type="neutral"
      variant="primary"
      iconSize="lg"
      @click=${this.onClose.bind(this)}
      data-testid="w3m-header-close"
    ></wui-icon-button>
    
  • The help button in leftHeaderTemplate(), around line 288-297:
    <wui-icon-button
      data-hidden=${!isConnectHelp}
      id="dynamic"
      icon="helpCircle"
      size="lg"
      iconSize="lg"
      type="neutral"
      variant="primary"
      @click=${this.onWalletHelp.bind(this)}
    ></wui-icon-button>
    

Neither passes an aria-label. Checked the shared component too,
packages/ui/src/composites/wui-icon-button/index.ts: it renders a plain
<button> around a <wui-icon> and does not accept or forward an
aria-label property at all, so no caller of wui-icon-button can label
one today. That is every icon-only button in the kit, not just these two,
but the close and help buttons in the header are the ones reachable in every
modal state, so they are the clearest reproduction.

Reproduction (no code changes, using the kit's own demo):

  1. Open any AppKit example app (e.g. the Next.js wagmi example in this repo)
    with a screen reader running, or open devtools' accessibility tree.
  2. Click the connect button to open the modal.
  3. Inspect the card: role alertdialog, aria-modal="true", no name. A
    screen reader announces only "dialog" with no further context.
  4. Inspect the top-left help icon button and the top-right close icon
    button: both are announced as "button" with no name.

Expected: the card announces something like "Connect Wallet" (or the
current view's heading) when it opens; the icon buttons announce "Help" and
"Close".

Actual: all three are silent, in every view the modal has, including the
account view, activity tab, and wrong-network screen that were not part of
the original report.

WCAG: 4.1.2 Name, Role, Value.
Rule: axe aria-dialog-name (card), axe button-name (both icon
buttons).

Suggested fix: give wui-icon-button an aria-label (or label)
property that it forwards to the inner <button>, pass one at each call
site ("Close", "Help"), and set aria-label (or aria-labelledby
pointing at the header title element) on the wui-card in
contentTemplate(), updating it as the router view and its heading change.

Found while auditing wallet-connect kits for accessibility. Happy to share
the reproduction script if useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions