Skip to content

Instantly share code, notes, and snippets.

@Seeyko
Created November 20, 2023 08:48
Show Gist options
  • Select an option

  • Save Seeyko/cd35dc5c1741600412d4cf6b5da89bcc to your computer and use it in GitHub Desktop.

Select an option

Save Seeyko/cd35dc5c1741600412d4cf6b5da89bcc to your computer and use it in GitHub Desktop.
React Autocomplete, with tailwind and daisyui
import React, { useState } from 'react';
const noOptionTitle = "No option !";
const Autocomplete = ({ options, name }: { options: string[], name: string }) => {
const [activeOption, setActiveOption] = useState(0);
const [filteredOptions, setFilteredOptions] = useState(options);
const [showOptions, setShowOptions] = useState(false);
const [userInput, setUserInput] = useState('');
const onChange = (e: any) => {
const userInput = e.currentTarget.value;
const filteredOptions: string[] = options.filter(
(option: string) => option.toLowerCase().indexOf(userInput.toLowerCase()) > -1
);
setActiveOption(0);
setFilteredOptions(filteredOptions);
setShowOptions(true);
setUserInput(userInput);
};
const onClick = (e: any) => {
const selectedOption = e.currentTarget.innerText;
setFilteredOptions([selectedOption]);
setActiveOption(0);
setShowOptions(false);
setUserInput(selectedOption);
};
const onKeyDown = (e: any) => {
if (e.keyCode === 13) {
setShowOptions(false);
const selectedOption = filteredOptions[activeOption];
setFilteredOptions([selectedOption]);
setActiveOption(0);
setUserInput(selectedOption);
} else if (e.keyCode === 38) {
if (activeOption === 0) {
return;
}
setActiveOption(activeOption - 1);
} else if (e.keyCode === 40) {
if (activeOption - 1 === filteredOptions.length) {
return;
}
setActiveOption(activeOption + 1);
}
};
let optionList;
if (showOptions) {
if (filteredOptions.length) {
optionList = (
<ul tabIndex={0} className="menu dropdown-content p-2 shadow-2xl bg-base-100 rounded-box w-full z-[1]">
{filteredOptions.map((option, index) => {
let className = index === activeOption ? 'bg-base-200' : '';
return (
<li key={option} onClick={(e) => onClick(e)}>
<a className={`${className} p-2 pointer-event-none`}>{option}</a>
</li>
);
})}
</ul>
);
} else {
optionList = (
<div className="dropdown-content p-2 shadow-2xl bg-base-100 rounded-box w-full z-10">
<div className="p-2">{noOptionTitle}</div>
</div>
);
}
}
return (
<React.Fragment>
<div className="dropdown">
<input
type="text"
name={name}
className="input input-bordered w-full pr-8"
onChange={onChange}
onKeyDown={onKeyDown}
onClick={() => setShowOptions(true)}
value={userInput}
></input>
<div className='absolute right-2 top-3 hover:cursor-pointer pointer-events-none'>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 9L14.1213 14.8787C12.9498 16.0503 11.0503 16.0503 9.8787 14.8787L4 9" stroke="black"
stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
{optionList}
</div>
</React.Fragment>
);
};
export default Autocomplete;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment