I have a working code to have 2 search bars with dropdown suggestions, selectable by both mouse and arrow keys in TypeScript and Fresh/Preact. In there I have to explicitly declare individual hooks for different lists:
const list1 = ['rabbits', 'raccoons', 'reindeer', 'red pandas', 'rhinoceroses', 'river otters', 'rattlesnakes', 'roosters'] as const
const list2 = ['jacaranda', 'jacarta', 'jack-o-lantern orange', 'jackpot', 'jade', 'jade green', 'jade rosin', 'jaffa'];
export default function SearchBar() {
const [resultList1, setResultList1] = useState<null | (typeof list1[number])[]>(null);
const [cursor1, setCursor1] = useState<Cursor>(0);
const [selectedItem1, setSelectedItem1] = useState<null | typeof list1[number]>(null); // State to track selected item for list 1
const [resultList2, setResultList2] = useState<null | (typeof list2[number])[]>(null);
const [cursor2, setCursor2] = useState<null | number>(0); // State to track selected item for list 2
const [selectedItem2, setSelectedItem2] = useState<null | typeof list2[number]>(null); // State to track selected item for list 2
/** activeList is used to determine whether the suggestion list should be popup or not */
const [activeList, setActiveList] = useState<null | '1' | '2'>(null); // State to track active list
And explicitly return individual divs for different lists.
<div
id='search-div-1'
className="search-bar-container"
>
<input
type="text"
placeholder={'Search list 1'}
onInput={(e) => {
setResultList1(list1.filter(item => item.includes((e.target as HTMLTextAreaElement).value)));
}}
onFocus={() => setActiveList('1')}
onKeyDown={(e) => handleKeyDown(e)}
/>
<br />
{resultList1 && activeList === '1' ? SuggestedList() : null}
Cursor: {cursor1}<br />
Selected item: <span id="Item 1">{selectedItem1}</span><br />
</div>
<div
id='search-div-2'
className="search-bar-container"
>
<input
type="text"
placeholder={'Search list 2'}
onInput={(e) => {
setResultList2(list2.filter(item => item.includes((e.target as HTMLTextAreaElement).value)));
}}
onFocus={() => setActiveList('2')}
onKeyDown={(e) => handleKeyDown(e)}
/>
<br />
{resultList2 && activeList === '2' ? SuggestedList() : null}
I wonder if this is a good approach or not. My next step for this is to have the suggested lists disappear when they are unfocused by integrating it with Detect click outside multiple components.