chore: front page search

This commit is contained in:
Kisuyo
2024-09-08 15:01:39 +02:00
parent b27fc3014e
commit 4ab241e115

View File

@@ -19,11 +19,11 @@ interface AutocompleteProps {
export function Autocomplete({ topics = [], onSelect, onInputChange }: AutocompleteProps): JSX.Element { export function Autocomplete({ topics = [], onSelect, onInputChange }: AutocompleteProps): JSX.Element {
const inputRef = useRef<HTMLInputElement>(null) const inputRef = useRef<HTMLInputElement>(null)
const isMounted = useMountedState()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const isMounted = useMountedState()
const [inputValue, setInputValue] = useState("") const [inputValue, setInputValue] = useState("")
const [isInitialOpen, setIsInitialOpen] = useState(true)
const [hasInteracted, setHasInteracted] = useState(false) const [hasInteracted, setHasInteracted] = useState(false)
const [showDropdown, setShowDropdown] = useState(false)
const initialShuffledTopics = useMemo(() => shuffleArray(topics).slice(0, 5), [topics]) const initialShuffledTopics = useMemo(() => shuffleArray(topics).slice(0, 5), [topics])
@@ -46,39 +46,31 @@ export function Autocomplete({ topics = [], onSelect, onInputChange }: Autocompl
const handleSelect = useCallback( const handleSelect = useCallback(
(topic: GraphNode) => { (topic: GraphNode) => {
// setInputValue(topicPrettyName)
setOpen(false) setOpen(false)
onSelect(topic.name) onSelect(topic.name)
}, },
[onSelect] [onSelect]
) )
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLDivElement>) => {
if ((e.key === "Backspace" || e.key === "Delete") && inputRef.current?.value === "") {
setOpen(true)
setIsInitialOpen(true)
}
if (!hasInteracted) {
setHasInteracted(true)
}
},
[hasInteracted]
)
const handleInputChange = useCallback( const handleInputChange = useCallback(
(value: string) => { (value: string) => {
setInputValue(value) setInputValue(value)
setOpen(true) setShowDropdown(true)
setIsInitialOpen(false) setHasInteracted(true)
onInputChange(value) onInputChange(value)
if (!hasInteracted) {
setHasInteracted(true)
}
}, },
[onInputChange, hasInteracted] [onInputChange]
) )
const handleFocus = useCallback(() => {
setHasInteracted(true)
}, [])
const handleClick = useCallback(() => {
setShowDropdown(true)
setHasInteracted(true)
}, [])
const commandKey = useMemo(() => { const commandKey = useMemo(() => {
return filteredTopics return filteredTopics
.map(topic => `${topic.name}:${topic.prettyName}:${topic.connectedTopics.join(",")}`) .map(topic => `${topic.name}:${topic.prettyName}:${topic.connectedTopics.join(",")}`)
@@ -100,12 +92,10 @@ export function Autocomplete({ topics = [], onSelect, onInputChange }: Autocompl
return ( return (
<Command <Command
key={commandKey}
className={cn("relative mx-auto max-w-md overflow-visible shadow-md", { className={cn("relative mx-auto max-w-md overflow-visible shadow-md", {
"rounded-lg border": !open, "rounded-lg border": !showDropdown,
"rounded-none rounded-t-lg border-l border-r border-t": open "rounded-none rounded-t-lg border-l border-r border-t": showDropdown
})} })}
onKeyDown={handleKeyDown}
> >
<div className={"relative flex items-center px-2 py-3"}> <div className={"relative flex items-center px-2 py-3"}>
<CommandPrimitive.Input <CommandPrimitive.Input
@@ -113,27 +103,23 @@ export function Autocomplete({ topics = [], onSelect, onInputChange }: Autocompl
value={inputValue} value={inputValue}
onValueChange={handleInputChange} onValueChange={handleInputChange}
onBlur={() => { onBlur={() => {
setTimeout(() => { setTimeout(() => setShowDropdown(false), 100)
setOpen(false)
setIsInitialOpen(true)
}, 100)
}} }}
onFocus={() => { onFocus={handleFocus}
setOpen(true) onClick={handleClick}
setIsInitialOpen(true) placeholder={filteredTopics[0]?.prettyName}
if (!hasInteracted) {
setHasInteracted(true)
}
}}
placeholder="Search for a topic..."
className={cn("placeholder:text-muted-foreground flex-1 bg-transparent px-2 outline-none")} className={cn("placeholder:text-muted-foreground flex-1 bg-transparent px-2 outline-none")}
autoFocus // Add this line
/> />
</div> </div>
<div className="relative"> <div className="relative">
<AnimatePresence> <AnimatePresence>
{open && ( {showDropdown && hasInteracted && (
<motion.div <motion.div
{...(isInitialOpen ? animationProps : {})} initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.1 }}
className="bg-background absolute left-0 right-0 z-10 -mx-px rounded-b-lg border-b border-l border-r border-t shadow-lg" className="bg-background absolute left-0 right-0 z-10 -mx-px rounded-b-lg border-b border-l border-r border-t shadow-lg"
> >
<CommandList className="max-h-56"> <CommandList className="max-h-56">