[a11y] Focus guard sentinels are exposed as nameless buttons in WebKit (axe button-name violation)
- 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
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