diff --git a/packages/mui-base/src/AutocompleteUnstyled/useAutocomplete.js b/packages/mui-base/src/AutocompleteUnstyled/useAutocomplete.js index 4ce10260898306..fbc53df429c480 100644 --- a/packages/mui-base/src/AutocompleteUnstyled/useAutocomplete.js +++ b/packages/mui-base/src/AutocompleteUnstyled/useAutocomplete.js @@ -309,7 +309,9 @@ export default function useAutocomplete(props) { } const setHighlightedIndex = useEventCallback(({ event, index, reason = 'auto' }) => { - highlightedIndexRef.current = index; + if (reason !== 'mouse') { + highlightedIndexRef.current = index; + } // does the index exist? if (index === -1) { @@ -326,9 +328,8 @@ export default function useAutocomplete(props) { return; } - const prev = listboxRef.current.querySelector('[role="option"].Mui-focused'); - if (prev) { - prev.classList.remove('Mui-focused'); + const prev = listboxRef.current.querySelector('[role="option"].Mui-focusVisible'); + if (prev && reason !== 'mouse') { prev.classList.remove('Mui-focusVisible'); } @@ -350,9 +351,10 @@ export default function useAutocomplete(props) { return; } - option.classList.add('Mui-focused'); - if (reason === 'keyboard') { + if (reason !== 'mouse') { option.classList.add('Mui-focusVisible'); + } else { + option.classList.add('Mui-focused'); } // Scroll active descendant into view. @@ -905,6 +907,10 @@ export default function useAutocomplete(props) { } }; + const handleOptionMouseLeave = (event) => { + event.currentTarget.classList.remove('Mui-focused'); + }; + const handleOptionMouseOver = (event) => { setHighlightedIndex({ event, @@ -1078,6 +1084,7 @@ export default function useAutocomplete(props) { tabIndex: -1, role: 'option', id: `${id}-option-${index}`, + onMouseLeave: handleOptionMouseLeave, onMouseOver: handleOptionMouseOver, onClick: handleOptionClick, onTouchStart: handleOptionTouchStart, diff --git a/packages/mui-material/src/Autocomplete/Autocomplete.test.js b/packages/mui-material/src/Autocomplete/Autocomplete.test.js index f9676895da5a6a..fb1cd75fe555c7 100644 --- a/packages/mui-material/src/Autocomplete/Autocomplete.test.js +++ b/packages/mui-material/src/Autocomplete/Autocomplete.test.js @@ -21,7 +21,7 @@ import { paperClasses } from '@mui/material/Paper'; import { iconButtonClasses } from '@mui/material/IconButton'; function checkHighlightIs(listbox, expected) { - const focused = listbox.querySelector(`.${classes.focused}`); + const focused = listbox.querySelector(`.${classes.focusVisible}`); if (expected) { if (focused) { @@ -1607,6 +1607,35 @@ describe('', () => { fireEvent.keyDown(textbox, { key: 'Enter' }); expect(handleChange.callCount).to.equal(1); }); + + it('should select keyboard highlighted option when enter is pressed', () => { + render( + } + />, + ); + + const textbox = screen.getByRole('combobox'); + + fireEvent.click(textbox); + + const listItemOne = screen.getByText('one'); + const listItemTwo = screen.getByText('two'); + + fireEvent.keyDown(textbox, { key: 'ArrowDown' }); + + fireEvent.mouseOver(listItemTwo); + + expect(listItemOne).to.have.class(classes.focusVisible); + expect(listItemTwo).to.have.class(classes.focused); + + fireEvent.keyDown(textbox, { key: 'Enter' }); + + expect(document.activeElement.value).to.equal('one'); + }); }); describe('prop: autoComplete', () => {