Repository: mui/material-ui (TypeScript)
Date: 2020-03-28 23:39:57+00:00
Task type: Bug Fix

Issue:
[Autocomplete] options list keeps jumping/scrolling back up when disableCloseOnSelect and multiple is set
<!-- Provide a general summary of the issue in the Title above -->
When you have a multi-value autocomplete component and have also set the `disableCloseOnSelect`, a weird jump/scroll back to the first selection occurs.

<!--
  Thank you very much for contributing to Material-UI by creating an issue! ❤️
  To avoid duplicate issues we ask you to check off the following list.
-->

<!-- Checked checkbox should look like this: [x] -->

- [x] The issue is present in the latest release.
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Current Behavior 😯
When `multiple` and `disableCloseOnSelect` are set to true, upon selecting new options in addition to previously selected options the scroll box of the options list will jump/scroll back up to the first selected option.

## Expected Behavior 🤔
The list's scroll state should remain exactly as is and should not scroll back up upon selection.

## Steps to Reproduce 🕹
I went to the [Autocomplete demo docs](https://material-ui.com/components/autocomplete/#multiple-values) and have forked the multiple-values demo section.

Demo: ![Demo](http://g.recordit.co/b7VREXzWVD.gif)
Codebox link: https://codesandbox.io/s/material-demo-weo4b

Steps:

1. Go to [Autocomplete demo docs](https://material-ui.com/components/autocomplete/#multiple-values)
2. Scroll down to multiple-values section, fork the example in codesandbox.io
3. Add `disableCloseOnSelect` to one of the autocomplete fields
4. Add mutiple selections and watch how the lists jumps back to the first selected option.


| Tech        | Version |
| ----------- | ------- |
| Material-UI | v4.8.0  |
| React       | v16.11.0 |
| Browser     | Canary Latest |




Issue discussion:

Solution patch:
diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
--- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
+++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
@@ -416,6 +416,17 @@ export default function useAutocomplete(props) {
 
     // Synchronize the value with the highlighted index
     if (!filterSelectedOptions && valueItem != null) {
+      const currentOption = filteredOptions[highlightedIndexRef.current];
+
+      // Keep the current highlighted index if possible
+      if (
+        multiple &&
+        currentOption &&
+        findIndex(value, (val) => getOptionSelected(currentOption, val)) !== -1
+      ) {
+        return;
+      }
+
       const itemIndex = findIndex(filteredOptions, (optionItem) =>
         getOptionSelected(optionItem, valueItem),
       );


Test patch:
diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
--- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
+++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
@@ -77,7 +77,7 @@ describe('<Autocomplete />', () => {
       checkHighlightIs('one');
     });
 
-    it('should set the focus on selected item when dropdown is expanded', () => {
+    it('should set the highlight on selected item when dropdown is expanded', () => {
       const { getByRole, setProps } = render(
         <Autocomplete
           {...defaultProps}
@@ -95,6 +95,29 @@ describe('<Autocomplete />', () => {
       setProps({ value: 'two' });
       checkHighlightIs('two');
     });
+
+    it('should keep the current highlight if possible', () => {
+      const { getByRole } = render(
+        <Autocomplete
+          {...defaultProps}
+          multiple
+          defaultValue={['one']}
+          options={['one', 'two', 'three']}
+          disableCloseOnSelect
+          renderInput={(params) => <TextField autoFocus {...params} />}
+        />,
+      );
+
+      function checkHighlightIs(expected) {
+        expect(getByRole('listbox').querySelector('li[data-focus]')).to.have.text(expected);
+      }
+
+      checkHighlightIs('one');
+      fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' });
+      checkHighlightIs('two');
+      fireEvent.keyDown(document.activeElement, { key: 'Enter' });
+      checkHighlightIs('two');
+    });
   });
 
   describe('prop: limitTags', () => {