From c4ef5c0ec26c58791554ca4ecf398c6cfd8b5527 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Sat, 5 Jul 2025 02:19:37 +0200 Subject: [PATCH] Fix autocomplete dropdown height --- CHANGELOG.md | 1 - src/components/InputAutocomplete.tsx | 30 +++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c78fa3c0..73d4892c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,6 @@ - Remove react-autobind dependency - Remove usage of legacy `childContextTypes` API - Replace react-autocomplete with Downshift in the autocomplete component -- Simplify autocomplete component and fix dropdown flicker when clicking - _...Add new stuff here..._ ### 🐞 Bug fixes diff --git a/src/components/InputAutocomplete.tsx b/src/components/InputAutocomplete.tsx index 370383f4..59558740 100644 --- a/src/components/InputAutocomplete.tsx +++ b/src/components/InputAutocomplete.tsx @@ -2,6 +2,8 @@ import React from 'react' import classnames from 'classnames' import {useCombobox} from 'downshift' +const MAX_HEIGHT = 140 + export type InputAutocompleteProps = { value?: string options?: any[] @@ -16,12 +18,21 @@ export default function InputAutocomplete({ 'aria-label': ariaLabel, }: InputAutocompleteProps) { const [input, setInput] = React.useState(value || '') + const menuRef = React.useRef(null) + const [maxHeight, setMaxHeight] = React.useState(MAX_HEIGHT) const filteredItems = React.useMemo(() => { const lv = input.toLowerCase() return options.filter((item) => item[0].toLowerCase().includes(lv)) }, [options, input]) + const calcMaxHeight = React.useCallback(() => { + if (menuRef.current) { + const space = window.innerHeight - menuRef.current.getBoundingClientRect().top + setMaxHeight(Math.min(space, MAX_HEIGHT)) + } + }, []) + const { isOpen, getMenuProps, @@ -48,10 +59,22 @@ export default function InputAutocomplete({ if (typeof v === 'string') { setInput(v) onChange(v === '' ? undefined : v) + openMenu() } }, }) + React.useEffect(() => { + if (isOpen) { + calcMaxHeight() + } + }, [isOpen, calcMaxHeight]) + + React.useEffect(() => { + window.addEventListener('resize', calcMaxHeight) + return () => window.removeEventListener('resize', calcMaxHeight) + }, [calcMaxHeight]) + React.useEffect(() => { setInput(value || '') }, [value]) @@ -67,9 +90,10 @@ export default function InputAutocomplete({ })} />
{isOpen && filteredItems.map((item, index) => (