From c950bd8d93382ee00a3ed1648423f8c52a2f91bf Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Sat, 24 Feb 2024 05:10:35 +0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20style:=20adjust=20the=20popover?= =?UTF-8?q?=20position=20based=20on=20the=20user=20screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/shared/Select/Select.tsx | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/shared/Select/Select.tsx b/packages/frontend/src/components/shared/Select/Select.tsx index 7c04252c..13c3d4a8 100644 --- a/packages/frontend/src/components/shared/Select/Select.tsx +++ b/packages/frontend/src/components/shared/Select/Select.tsx @@ -5,6 +5,8 @@ import React, { useMemo, useCallback, MouseEvent, + useRef, + useEffect, } from 'react'; import { useMultipleSelection, useCombobox } from 'downshift'; import { SelectTheme, selectTheme } from './Select.theme'; @@ -62,6 +64,34 @@ export const MultiSelect: React.FC = ({ const [inputValue, setInputValue] = useState(''); const [selectedItem, setSelectedItem] = useState(null); const [dropdownOpen, setDropdownOpen] = useState(false); + const [dropdownPosition, setDropdownPosition] = useState<'top' | 'bottom'>( + 'bottom', + ); + const popoverRef = useRef(null); // Ref for the popover + const inputWrapperRef = useRef(null); // Ref for the input wrapper + + // Calculate and update popover position + useEffect(() => { + if (dropdownOpen && popoverRef.current && inputWrapperRef.current) { + const popover = popoverRef.current; + // @ts-expect-error – we know it's not null + const input = inputWrapperRef.current.getBoundingClientRect(); + const spaceBelow = window.innerHeight - input.bottom; + const spaceAbove = input.top; + // @ts-expect-error – we know it's not null + const popoverHeight = popover.offsetHeight; + + // Determine if there's enough space below + if (spaceBelow >= popoverHeight) { + setDropdownPosition('bottom'); + } else if (spaceAbove >= popoverHeight) { + setDropdownPosition('top'); + } else { + // Default to bottom if neither has enough space, but you could also set logic to choose the side with more space + setDropdownPosition('bottom'); + } + } + }, [dropdownOpen]); // Re-calculate whenever the dropdown is opened const handleSelectedItemChange = (selectedItem: DropdownItem | null) => { setSelectedItem(selectedItem); @@ -211,6 +241,7 @@ export const MultiSelect: React.FC = ({
{renderLabels}
0, })} @@ -250,7 +281,15 @@ export const MultiSelect: React.FC = ({ {renderRightIcon}
{renderHelperText} -
    +
      {isOpen && filteredItems.length !== 0 ? ( filteredItems.map((item, index) => (