[a11y] Focus guard sentinels are exposed as nameless buttons in WebKit (axe button-name violation)
Author: QusayNaserFHSCreated Jul 15, 2026Updated Sep 11, 2026
Labelstype: expected behavior
Summary
The visually-hidden focus-guard sentinels Base UI renders around trapped popups —
<span data-type="inside" tabindex="0" role="button" data-base-ui-focus-guard="" data-base-ui-inert=""
style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"></span>— 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/react1.6.0- Playwright 1.61.1 (
webkit),axe-core4.12.1 via@axe-core/playwright - Reproduces deterministically (not load/timing dependent), light theme, headless
Repro
- Render any focus-trapping surface (observed with a Dialog-based sheet/drawer and a command-palette dialog) in the open state.
- Run an axe scan in Playwright WebKit.
button-nameviolations 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.
Source: mui/base-ui