mui / mui/base-ui

[combobox] Internal dismiss button's aria-label "Dismiss" is hardcoded and cannot be localized

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

Description

## Summary

The Combobox renders an internal, visually hidden dismiss button
(`ComboboxInternalDismissButton`) so that screen reader users can close the
popup. Its accessible name is the hardcoded English string `"Dismiss"`:

```tsx
// packages/react/src/combobox/utils/ComboboxInternalDismissButton.tsx

```

There is currently no way to localize it. In any non-English app, screen
reader users hear an English label on this control. `Autocomplete` is affected
as well, since it reuses the Combobox popup part.

## Where it comes from

- `ComboboxPopup` (and `ComboboxInput` when the input lives inside the popup)
render `ComboboxInternalDismissButton` whenever `focusManagerModal` is true —
which is always the case in the common "input outside the popup" layout
(`focusManagerModal = !inputInsidePopup || modal`).
- The component is `@internal`, so there is no part to target.
- `Combobox.Root`'s `locale` prop only affects string comparison for
filtering, not built-in labels.
- No `translations`/label prop exists on `Root`, `Popup` or `Positioner`.

## Why it matters

The affordance itself is great (an escape hatch for AT users) — but a
hardcoded English name is a WCAG 2.5.3 / label-in-language concern and blocks
strict conformance audits in non-English apps. Concretely: we hit this while
running a French RGAA (public sector accessibility) audit — the audit flags a
control whose name is not in the page language, and we have no application-side
lever to fix it.

## Proposed solutions (happy to send a PR for whichever you prefer)

1. **A label prop** on `Combobox.Root` (e.g. `dismissButtonLabel` or a small
`translations` object for built-in strings) — smallest change, keeps the
auto-rendered behavior.
2. **A public `Combobox.Close` part** with `visuallyHidden`, following the
direction taken for Popover in #2722 — more flexible, but changes the
"rendered automatically" model unless it only overrides the internal one.
3. A library-wide localization mechanism for all built-in strings, if more
hardcoded labels are expected to appear over time.

Option 1 seems like the pragmatic fix; option 3 is the long-term answer if
other internal strings exist or are planned.

## Environment

- `@base-ui/react` 1.6.0 (also present on current `master`)
- Layout: `Combobox.Input` outside the popup (Portal + Positioner + Popup),
uncontrolled `open`

Contributor guide

Open the contributing guide

Research direction

Start with packages/react/src/combobox/utils/ComboboxInternalDismissButton.tsx and trace how ComboboxPopup and ComboboxInput render it when focusManagerModal is true. Review the Combobox.Root, Popup, and Positioner APIs, then confirm the preferred localization approach. Done means the dismiss control has a consumer-configurable non-English accessible name, including when reused by Autocomplete.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.