Goal
I want to have two search bars, and each of them can:
- Display suggestions as typing
- Use arrow keys to select item
- Each item can be customized
Because of the last bullet I don’t want to use <datalist>
tag as it’s limited in style. I also use Deno Fresh, which is based on Preact, which is based on React. At the time I wasn’t aware of guides on navigate through list by arrow keys in React, but in vanilla JS, and I think using the vanilla version will be simpler, so currently I’m using it.
Problem
When a list is navigated by keyboard, the other is also triggered. My idea is to have the script targets different lists, and when users unfocus an input field it will be deactivated. I try having this on the script:
if (list === 'deactivate') return
And on each handler I have:
onBlur={(e) => script('deactivate')}
But it still doesn’t work. Do you have any suggestion?
Code
search.jsx
:
export default function SearchBar() {
const [keyword1, setKeyword1] = useState("");
const [keyword2, setKeyword2] = useState("");
const list1 = [ 'rabbits', 'raccoons', 'reindeer', 'red pandas', 'rhinoceroses', 'river otters', 'rattlesnakes', 'roosters' ]
const list2 = [ 'jacaranda', 'jacarta', 'jack-o-lantern orange', 'jackpot', 'jade', 'jade green', 'jade rosin', 'jaffa' ]
return (
<div className="search-bar-container">
<input
type="text"
placeholder={'Search list 1'}
value={keyword1}
onInput={(e) => {
setKeyword1(e.target.value);
script('1');
}}
onBlur={(e) => script('deactivate')}
/>
<br />
<ul id={'Suggested list 1'}>
{keyword1 !== '' ? list1.filter(keyword => keyword.includes(keyword1)).map(
(item) => <li>{item}</li>,
) : ''}
</ul>
<div>
Your selected item is :<span id="Item 1"></span>
</div>
<div className="search-bar-container">
<input
type="text"
placeholder={'Search list 2'}
value={keyword2}
onInput={(e) => {
setKeyword2(e.target.value);
script('2');
}}
onBlur={(e) => script('deactivate') }
/>
<br />
<ul id={'Suggested list 2'}>
{keyword2 !== '' ? list2.filter(keyword => keyword.includes(keyword2)).map(
(item) => <li>{item}</li>,
): ''}
</ul>
<div>
Your selected item is :<span id="Item 2"></span>
</div>
</div>
</div>
);
}
script.ts
:
export function script(list: "1" | "2" | 'deactivate') {
if (list === 'deactivate') return
if (window !== undefined) {
const ul = document.getElementById(`Suggested list ${list}`);
const result = document.getElementById(`Item ${list}`);
//the rest of the script
Full code. Somehow CodeSandbox keeps having twind error even when I don’t. This does run in my machine.