mui / mui/base-ui

[a11y] Focus guard sentinels are exposed as nameless buttons in WebKit (axe button-name violation)

Open
#5,237 1 comment 0 reactions 0 assignees View on GitHub
type: expected behavior
Dominant language
TypeScript
Stars
10.9k
Forks
543
Avg merge
1d 20h
Merged PRs (30d)
101

Description

### Summary

The visually-hidden focus-guard sentinels Base UI renders around trapped popups —

```html

```

— are focusable (`tabindex="0"`), carry `role="button"`, and have **no accessible name**. In Chromium and Firefox they are excluded from the accessibility tree, so axe passes. In **WebKit** they are exposed, and axe flags **`button-name`** (serious) on every guard.

### Environment

- `@base-ui/react` **1.6.0**
- Playwright **1.61.1** (`webkit`), `axe-core` **4.12.1** via `@axe-core/playwright`
- Reproduces deterministically (not load/timing dependent), light theme, headless

### Repro

1. Render any focus-trapping surface (observed with a Dialog-based sheet/drawer and a command-palette dialog) in the open state.
2. Run an axe scan in Playwright WebKit.
3. `button-name` violations are reported against the `[data-base-ui-focus-guard]` spans (selector observed: `span[data-type="inside"][data-base-ui-focus-guard=""][role="button"]`). The same scan passes in Chromium and Firefox.

### Expected

Focus guards should be invisible to assistive technology — e.g. `aria-hidden="true"` on the sentinels (they are focus plumbing, not actionable controls), or an accessible name if they are intentionally exposed.

### Impact

- Safari/VoiceOver users can land on an unnamed "button" at popup boundaries.
- Cross-engine axe gates (CI a11y suites running the WebKit engine) fail on every story/page with an open trapped popup, with no workaround available from userland — the guards are re-rendered by Base UI on focus changes, so consumer-side DOM patching is not durable.

Happy to provide a minimal repro repository if useful.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the open trapped-popup case in Playwright WebKit and inspect span[data-type="inside"][data-base-ui-focus-guard=""][role="button"]. Trace where these focus guards are rendered and rerendered; done means WebKit axe scans report no button-name violations while popup focus trapping still works.

Written by the indexing model from the issue text.

Assessment

Tech stack
playwright, react, typescript
Domain
accessibility, frontend, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.