Skip to content

[autocomplete] Improve highlight tracking and selection state#48219

Open
mj12albert wants to merge 4 commits intomui:masterfrom
mj12albert:autocomplete/highlight-and-selection-1of5
Open

[autocomplete] Improve highlight tracking and selection state#48219
mj12albert wants to merge 4 commits intomui:masterfrom
mj12albert:autocomplete/highlight-and-selection-1of5

Conversation

@mj12albert
Copy link
Copy Markdown
Member

@mj12albert mj12albert commented Apr 7, 2026

Fixes #20602
Fixes #27137
Fixes #46718

Adds highlightReasonRef internally to better handle edge cases created by the item highlight and other interactions.

Codex suggests using pointer events as a better touch/mouse detection strategy to what is currently being used, which is more robust for hybrid devices (iPad with a bluetooth keyboard) but we could do that separately.

Manual testing steps:

1. autoSelect should not select mouse-hovered options on blur: #20602

  1. Combo box demo → add autoSelect via the code editor
  2. Click the input to open the popup
  3. Hover your mouse over an option (don’t click)
  4. Click outside the component to blur

Expected: No option selected — input stays empty

Current: The hovered option IS selected — its value appears in the input after blur

Variation with autoHighlight:

  1. Combo box demo → add both autoSelect and autoHighlight
  2. Click the input to open the popup, observe first option is auto-highlighted
  3. Hover your mouse over that same first option
  4. Click outside to blur

Expected: No option selected (the hover overrides the programmatic highlight reason)

Current: The first option is selected on blur, even though the user only hovered over it.


2. freeSolo Enter should prefer typed text over auto-highlighted match #27137

  1. Free solo demo
  2. Type "The Godfather" and press Enter to select it
  3. Click back into the input
  4. Press Backspace 5 times (input becomes "The Godf" — still matches "The Godfather" in the dropdown)
  5. Press Enter

Expected: "The Godf" is accepted as free text, NOT "The Godfather"

Current (master): "The Godfather" is re-selected (the full original value), not "The Godf". The programmatic highlight from syncHighlightedIndex (which matches the old value) wins over the typed text.


3. Touch-scroll + Enter selects wrong item #46718

This requires a touch device + software keyboard

  1. Combo box demo
  2. Touch the textbox to open the popup
  3. Touch an option to start a drag, then drag to scroll the list (don't lift or tap, it must be dragged so the browser treats it as a scroll gesture)
  4. When the list scrolls a bit, release finger, press Enter ("Return" on iPhone keyboard)

Expected: Popup closes with no option selected

Current (master): The option that was under the initial touch point (before scrolling) is selected. The stale highlight from touchstart is persisted through the scroll, and Enter commits it.

@mj12albert mj12albert added type: bug It doesn't behave as expected. scope: autocomplete Changes related to the autocomplete. This includes ComboBox. labels Apr 7, 2026
@mui-bot
Copy link
Copy Markdown

mui-bot commented Apr 7, 2026

Netlify deploy preview

https://deploy-preview-48219--material-ui.netlify.app/

Bundle size report

Bundle Parsed size Gzip size
@mui/material 🔺+435B(+0.09%) 🔺+136B(+0.09%)
@mui/lab 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

Generated by 🚫 dangerJS against 1ffd021

Comment on lines +978 to +985
if (
highlightedIndexRef.current !== -1 &&
popupOpen &&
shouldSelectHighlighted &&
// After a touch-scroll the highlight is stale (the user scrolled
// past it), so skip selection until the next deliberate interaction.
!touchScrolledRef.current
) {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This if now accounts for both #27137 and #46718

@mj12albert mj12albert force-pushed the autocomplete/highlight-and-selection-1of5 branch 2 times, most recently from c4c814d to 587749d Compare April 7, 2026 23:24
@mj12albert mj12albert force-pushed the autocomplete/highlight-and-selection-1of5 branch from 587749d to b04c1f0 Compare April 10, 2026 16:28
@mj12albert mj12albert marked this pull request as ready for review April 10, 2026 16:28
Comment on lines +1112 to +1115
// Auto-select the highlighted option on blur, but only if the highlight
// came from keyboard navigation or was set programmatically (autoHighlight).
// Mouse hover and touch should not trigger selection — the user may have
// moved the pointer over an option without intending to commit to it.
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.

Looking at this and the related test: (should not select a mouse-hovered option on blur even if already highlighted) i.e autoSelect + autoHighlight prop combination.

Right now, the first auto-highlighted option is not selected on blur if it was mouse-hovered, but is selected if it wasn't hovered. This feels inconsistent and confusing.

Instead, if autoHighlight is active (first option highlighted), it should be selected on blur regardless of hovered over that option or not.

The “don't select on hover + blur” behavior should apply only to other (non auto-highlighted) options.

Copy link
Copy Markdown
Member Author

@mj12albert mj12albert Apr 14, 2026

Choose a reason for hiding this comment

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

I don't agree with changing this behavior in this PR, mouse hover alone should not commit a value on blur.

IMO the fact that the hovered option happened to already be autoHighlight-ed does not make it a stronger/deliberate intent of user selection

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.

Do we have an official spec for this somewhere which we can follow?

} else if (popupOpen && touchScrolledRef.current) {
// The highlight is stale from a touch-scroll — close without selecting.
event.preventDefault();
handleClose(event, 'escape');
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.

Is escape reason correct here? Since we are closing on Enter with mobile keyboard.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Technically no, but we don't have a Esc close reason and this is the closest while strictly avoiding breaking changes

Though we could widen the type and it should be safe

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.

This looks a very rare case where this will trigger so as to widen the types, but it's up to you.

Comment on lines +1156 to +1160
// Called after handleOpen so it overrides handleOpen's setInputPristine(true)
// when the first keystroke also opens the popup.
if (valueChanged) {
setInputPristine(false);
}
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.

Is this a separate regression or it's covered in the tests above?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: autocomplete Changes related to the autocomplete. This includes ComboBox. type: bug It doesn't behave as expected.

Projects

None yet

3 participants