Skip to content

[autocomplete] Wrap the no results and loading messages in a status element#48690

Merged
silviuaavram merged 10 commits into
mui:masterfrom
silviuaavram:feat/no-options-slot-for-autocomplete
Jul 7, 2026
Merged

[autocomplete] Wrap the no results and loading messages in a status element#48690
silviuaavram merged 10 commits into
mui:masterfrom
silviuaavram:feat/no-options-slot-for-autocomplete

Conversation

@silviuaavram

@silviuaavram silviuaavram commented Jun 18, 2026

Copy link
Copy Markdown
Member

Fixes #48666

Add a new status slot that wraps the "no options" and "loading" elements with a container element. The container renders with role="status", aria-live="polite", and aria-atomic="true" so assistive technologies announce the absence of options without requiring the popup to be open.

Changes

  • Add the status slot via useSlot backed by a plain 'div' (no styled wrapper needed)
  • Assign the new status CSS class to the container element so consumers can style it
  • Add status to autocompleteClasses and AutocompleteClasses
  • Add AutocompleteStatusSlotPropsOverrides augmentation interface
  • Add status to AutocompleteSlots and AutocompleteSlotsAndSlotProps
  • Update PropTypes for slots (status) and slotProps (status)
  • Regenerate API docs

Copilot AI review requested due to automatic review settings June 18, 2026 12:58
@silviuaavram silviuaavram added accessibility a11y scope: autocomplete Changes related to the autocomplete. This includes ComboBox. labels Jun 18, 2026
@code-infra-dashboard

code-infra-dashboard Bot commented Jun 18, 2026

Copy link
Copy Markdown

Deploy preview

https://deploy-preview-48690--material-ui.netlify.app/
QR code for https://deploy-preview-48690--material-ui.netlify.app/

Bundle size

Bundle Parsed size Gzip size
@mui/material 🔺+256B(+0.05%) 🔺+105B(+0.07%)
@mui/lab 0B(0.00%) 0B(0.00%)
@mui/private-theming 0B(0.00%) 0B(0.00%)
@mui/system 0B(0.00%) 0B(0.00%)
@mui/utils 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Autocomplete to improve assistive-technology announcements when there are no matching options by introducing a new noOptions slot that provides a live-region status container around the existing “no options” content.

Changes:

  • Add a noOptions slot (and slotProps.noOptions) and wrap the no-options content in a role="status" live region (aria-live="polite", aria-atomic="true").
  • Extend TypeScript typings (slot + overrides augmentation) and PropTypes to include the new slot.
  • Add/adjust tests and regenerate API docs reflecting the new slot.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/mui-material/src/Autocomplete/Autocomplete.js Adds noOptions slot via useSlot and wraps the no-options message in a status live region.
packages/mui-material/src/Autocomplete/Autocomplete.d.ts Adds noOptions to AutocompleteSlots and slot-props typing + overrides interface.
packages/mui-material/src/Autocomplete/Autocomplete.spec.tsx Adds TS coverage for slots.noOptions / slotProps.noOptions usage (including ref).
packages/mui-material/src/Autocomplete/Autocomplete.test.js Adds tests around noOptionsText rendering and the status container behavior.
docs/translations/api-docs/autocomplete/autocomplete.json Updates slot descriptions to include noOptions.
docs/pages/material-ui/api/autocomplete.json Updates API docs output for the new noOptions slot and slotProps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/mui-material/src/Autocomplete/Autocomplete.js Outdated
Comment thread packages/mui-material/src/Autocomplete/Autocomplete.js Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

docs/translations/api-docs/autocomplete/autocomplete.json:323

  • In the translations JSON, noOptions has been moved from classDescriptions to slotDescriptions, implying noOptions is now a slot (and no longer a documented utility class). However, the current implementation still applies classes.noOptions to the inner message wrapper (<AutocompleteNoOptions className={classes.noOptions} ...>), while the new noOptions slot container has no class.

This makes the generated docs inconsistent with the actual DOM/class placement. Consider aligning the implementation with the slot documentation (or vice-versa) and regenerating these files.

  "slotDescriptions": {
    "clearIndicator": "The component used to render the clear indicator element.",
    "listbox": "The component used to render the listbox.",
    "noOptions": "The component used to render the &quot;no options&quot; container.",
    "paper": "The component used to render the body of the popup.",
    "popper": "The component used to position the popup.",
    "popupIndicator": "The component used to render the popup indicator element.",
    "root": "The component that renders the root."
  }

Comment thread packages/mui-material/src/Autocomplete/Autocomplete.js Outdated
Comment thread packages/mui-material/src/Autocomplete/Autocomplete.js
Comment thread docs/pages/material-ui/api/autocomplete.json
Comment thread packages/mui-material/src/Autocomplete/Autocomplete.js Outdated
Comment thread packages/mui-material/src/Autocomplete/Autocomplete.js
Comment thread packages/mui-material/src/Autocomplete/Autocomplete.js
@silviuaavram
silviuaavram force-pushed the feat/no-options-slot-for-autocomplete branch from e7139c4 to 29583ca Compare June 25, 2026 11:43
@silviuaavram silviuaavram changed the title [autocomplete] Wrap the no results message in a status element [autocomplete] Wrap the no results and loading messages in a status element Jul 2, 2026

@ZeeshanTamboli ZeeshanTamboli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I inspected the DOM. The popup now always has an extra empty accessible live region sibling before the listbox:

<div role="status" ...></div>
<ul role="listbox">...</ul>

Is this expected? Wouldn't it be better to render the status slot only when it has content ("no options" or "loading") within it?

@silviuaavram

Copy link
Copy Markdown
Member Author

I inspected the DOM. The popup now always has an extra empty accessible live region sibling before the listbox:

<div role="status" ...></div>
<ul role="listbox">...</ul>

Is this expected? Wouldn't it be better to render the status slot only when it has content ("no options" or "loading") within it?

Screen readers have a hard time picking up updates when elements are added and removed. When using live regions, it is recommended to leave the live region element always in the DOM, update with content when needed, then remove / replace the content.

@ZeeshanTamboli

ZeeshanTamboli commented Jul 6, 2026

Copy link
Copy Markdown
Member

I inspected the DOM. The popup now always has an extra empty accessible live region sibling before the listbox:

<div role="status" ...></div>
<ul role="listbox">...</ul>

Is this expected? Wouldn't it be better to render the status slot only when it has content ("no options" or "loading") within it?

Screen readers have a hard time picking up updates when elements are added and removed. When using live regions, it is recommended to leave the live region element always in the DOM, update with content when needed, then remove / replace the content.

This is the behaviour I found in Base UI Combobox as well: https://base-ui.com/react/components/combobox. 👍

@ZeeshanTamboli ZeeshanTamboli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

I tested with Narrator and NVDA screen readers on Windows 11 at https://deploy-preview-48690--material-ui.netlify.app/material-ui/react-autocomplete/#githubs-picker. Narrator is not announcing "No labels", while NVDA is announcing it. Maybe Narrator does not support aria-live yet.

@ZeeshanTamboli ZeeshanTamboli added the type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. label Jul 6, 2026
@silviuaavram
silviuaavram merged commit e50ce16 into mui:master Jul 7, 2026
22 checks passed
@silviuaavram
silviuaavram deleted the feat/no-options-slot-for-autocomplete branch July 7, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accessibility a11y scope: autocomplete Changes related to the autocomplete. This includes ComboBox. type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Autocomplete] hardcoded role="presentation" on noOptionsText container suppresses semantics for some screen readers

5 participants