diff --git a/packages/eds-core-react/src/components/Autocomplete/Autocomplete.tsx b/packages/eds-core-react/src/components/Autocomplete/Autocomplete.tsx index 79b45941c1..9b8c4c994c 100644 --- a/packages/eds-core-react/src/components/Autocomplete/Autocomplete.tsx +++ b/packages/eds-core-react/src/components/Autocomplete/Autocomplete.tsx @@ -10,6 +10,7 @@ import { EventHandler, SyntheticEvent, DOMAttributes, + FocusEvent, } from 'react' import { useCombobox, @@ -202,6 +203,21 @@ const findPrevIndex: IndexFinderType = ({ return prevIndex } +/*When a user clicks the StyledList scrollbar, the input looses focus which breaks downshift + * keyboard navigation in the list. This code returns focus to the input on mouseUp + */ +const handleListFocus = (e: FocusEvent) => { + e.preventDefault() + e.stopPropagation() + window?.addEventListener( + 'mouseup', + () => { + ;(e.relatedTarget as HTMLInputElement)?.focus() + }, + { once: true }, + ) +} + const defaultOptionDisabled = () => false type OptionLabelProps = T extends string | number @@ -530,6 +546,18 @@ function AutocompleteInner( }, onHighlightedIndexChange({ highlightedIndex, type }) { if ( + type == useCombobox.stateChangeTypes.InputClick || + (type == useCombobox.stateChangeTypes.InputKeyDownArrowDown && + !isOpen) || + (type == useCombobox.stateChangeTypes.InputKeyDownArrowUp && !isOpen) + ) { + //needs delay for dropdown to render before calling scroll + setTimeout(() => { + rowVirtualizer.scrollToIndex(highlightedIndex, { + align: allowSelectAll ? 'center' : 'auto', + }) + }, 1) + } else if ( type !== useCombobox.stateChangeTypes.ItemMouseMove && type !== useCombobox.stateChangeTypes.MenuMouseLeave && highlightedIndex >= 0 @@ -767,7 +795,7 @@ function AutocompleteInner( } }, [refs.reference, refs.floating, update, isOpen]) - useEffect(() => { + useIsomorphicLayoutEffect(() => { if (isOpen) { refs.floating.current.showPopover() } else { @@ -797,6 +825,7 @@ function AutocompleteInner( popover="manual" {...getFloatingProps({ ref: refs.setFloating, + onFocus: handleListFocus, style: { position: strategy, top: y || 0,