From bc803fc5520d0217c00008e2f659fc91f2d6419c Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Thu, 30 Jun 2022 11:19:26 +0200 Subject: [PATCH] =?UTF-8?q?feat(editor):=20=F0=9F=9A=B8=20Arrow=20&=20Ente?= =?UTF-8?q?r=20commands=20for=20dropdowns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/shared/SearchableDropdown.tsx | 39 ++++++++- .../components/shared/VariableSearchInput.tsx | 85 +++++++++++++++---- 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/apps/builder/components/shared/SearchableDropdown.tsx b/apps/builder/components/shared/SearchableDropdown.tsx index c07c14b7ce..6d0b5d5e17 100644 --- a/apps/builder/components/shared/SearchableDropdown.tsx +++ b/apps/builder/components/shared/SearchableDropdown.tsx @@ -13,7 +13,7 @@ import { import { Variable } from 'models' import { useState, useRef, useEffect, ChangeEvent } from 'react' import { useDebouncedCallback } from 'use-debounce' -import { env } from 'utils' +import { env, isDefined } from 'utils' import { VariablesButton } from './buttons/VariablesButton' type Props = { @@ -47,7 +47,11 @@ export const SearchableDropdown = ({ ) .slice(0, 50), ]) + const [keyboardFocusIndex, setKeyboardFocusIndex] = useState< + number | undefined + >() const dropdownRef = useRef(null) + const itemsRef = useRef<(HTMLButtonElement | null)[]>([]) const inputRef = useRef(null) useEffect( @@ -96,6 +100,7 @@ export const SearchableDropdown = ({ const handleItemClick = (item: string) => () => { setInputValue(item) debounced(item) + setKeyboardFocusIndex(undefined) onClose() } @@ -125,9 +130,31 @@ export const SearchableDropdown = ({ }, 100) } - const handleKeyUp = () => { - if (!inputRef.current?.selectionStart) return - setCarretPosition(inputRef.current.selectionStart) + const handleKeyUp = (e: React.KeyboardEvent) => { + if (inputRef.current?.selectionStart) + setCarretPosition(inputRef.current.selectionStart) + if (e.key === 'Enter' && isDefined(keyboardFocusIndex)) { + handleItemClick(filteredItems[keyboardFocusIndex])() + return setKeyboardFocusIndex(undefined) + } + if (e.key === 'ArrowDown') { + if (keyboardFocusIndex === undefined) return setKeyboardFocusIndex(0) + if (keyboardFocusIndex === filteredItems.length - 1) return + itemsRef.current[keyboardFocusIndex + 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + return setKeyboardFocusIndex(keyboardFocusIndex + 1) + } + if (e.key === 'ArrowUp') { + if (keyboardFocusIndex === undefined) return + if (keyboardFocusIndex === 0) return setKeyboardFocusIndex(undefined) + itemsRef.current[keyboardFocusIndex - 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + setKeyboardFocusIndex(keyboardFocusIndex - 1) + } } return ( @@ -170,6 +197,7 @@ export const SearchableDropdown = ({ {filteredItems.map((item, idx) => { return ( - )} + {isCreateVariableButtonDisplayed && ( + + )} {filteredItems.length > 0 && ( <> {filteredItems.map((item, idx) => { + const indexInList = isCreateVariableButtonDisplayed + ? idx + 1 + : idx return (