Select: Infer dropdown menu position (#42446)

* Infer dropdown menu position when using asynchronously loaded options

* Infer position only when the menu is opened when the component is created

* Add link to react-select bug

* Update docs
This commit is contained in:
Piotr Jamróz 2021-12-13 14:59:51 +01:00 committed by GitHub
parent f9a8e41710
commit cf2063f19a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,4 +1,4 @@
import React, { ComponentProps, useCallback } from 'react';
import React, { ComponentProps, useCallback, useEffect, useRef, useState } from 'react';
import { default as ReactSelect } from 'react-select';
import Creatable from 'react-select/creatable';
import { default as ReactAsyncSelect } from 'react-select/async';
@ -144,6 +144,27 @@ export function SelectBase<T>({
}
const theme = useTheme2();
const styles = getSelectStyles(theme);
const reactSelectRef = useRef<{ controlRef: HTMLElement }>(null);
const [closeToBottom, setCloseToBottom] = useState<boolean>(false);
// Infer the menu position for asynchronously loaded options. menuPlacement="auto" doesn't work when the menu is
// automatically opened when the component is created (it happens in SegmentSelect by setting menuIsOpen={true}).
// We can remove this workaround when the bug in react-select is fixed: https://github.com/JedWatson/react-select/issues/4936
// Note: we use useEffect instead of hooking into onMenuOpen due to another bug: https://github.com/JedWatson/react-select/issues/3375
useEffect(() => {
if (
loadOptions &&
isOpen &&
reactSelectRef.current &&
reactSelectRef.current.controlRef &&
menuPlacement === 'auto'
) {
const distance = window.innerHeight - reactSelectRef.current.controlRef.getBoundingClientRect().bottom;
setCloseToBottom(distance < maxMenuHeight);
}
}, [maxMenuHeight, menuPlacement, loadOptions, isOpen]);
const onChangeWithEmpty = useCallback(
(value: SelectValue<T>, action: ActionMeta) => {
if (isMulti && (value === undefined || value === null)) {
@ -204,7 +225,7 @@ export function SelectBase<T>({
minMenuHeight,
maxVisibleValues,
menuIsOpen: isOpen,
menuPlacement,
menuPlacement: menuPlacement === 'auto' && closeToBottom ? 'top' : menuPlacement,
menuPosition,
menuShouldBlockScroll: true,
menuPortalTarget: menuShouldPortal ? document.body : undefined,
@ -246,6 +267,7 @@ export function SelectBase<T>({
return (
<>
<ReactSelectComponent
ref={reactSelectRef}
components={{
MenuList: SelectMenu,
Group: SelectOptionGroup,