staff_data/apps/web/src/components/layout/main/search-bar.tsx

55 lines
2.3 KiB
TypeScript

import { useState, useRef, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { SearchDropdown } from './search-dropdown';
import { MagnifyingGlassIcon, XMarkIcon } from '@heroicons/react/24/outline';
import { useClickOutside } from '@web/src/hooks/useClickOutside';
interface SearchBarProps {
recentSearches: string[];
}
export function SearchBar({ recentSearches }: SearchBarProps) {
const [searchFocused, setSearchFocused] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
const searchRef = useRef<HTMLDivElement>(null);
useClickOutside(searchRef, () => setSearchFocused(false))
return (
<div ref={searchRef} className="relative max-w-xl w-full px-4">
<div className={`
relative flex items-center w-full h-10 rounded-full
transition-all duration-300 ease-in-out
${searchFocused
? 'bg-white shadow-md ring-2 ring-blue-500'
: 'bg-gray-100 hover:bg-gray-200'
}
`}>
<MagnifyingGlassIcon className="h-5 w-5 ml-3 text-gray-500" />
<input
type="text"
placeholder="Search for courses, topics, or instructors..."
className="w-full h-full bg-transparent px-3 outline-none text-sm"
onFocus={() => setSearchFocused(true)}
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
{searchQuery && (
<motion.button
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
className="p-1.5 mr-2 rounded-full hover:bg-gray-200"
onClick={() => setSearchQuery('')}
>
<XMarkIcon className="h-4 w-4 text-gray-500" />
</motion.button>
)}
</div>
<SearchDropdown
searchFocused={searchFocused}
searchQuery={searchQuery}
recentSearches={recentSearches}
setSearchQuery={setSearchQuery}
/>
</div>
);
}