parent
6186e12b05
commit
8d25eabe3a
3 changed files with 111 additions and 14 deletions
@ -0,0 +1,66 @@ |
|||||||
|
import { useRef, useState } from 'react'; |
||||||
|
import { useOutsideClick } from '../../hooks/use-outside-click'; |
||||||
|
import { ChevronDown } from 'lucide-react'; |
||||||
|
|
||||||
|
type SortOption = { |
||||||
|
label: string; |
||||||
|
value: string; |
||||||
|
}; |
||||||
|
|
||||||
|
const sortOptions: SortOption[] = [ |
||||||
|
{ label: 'Latest First', value: 'latest' }, |
||||||
|
{ label: 'Oldest First', value: 'oldest' }, |
||||||
|
{ label: 'Highest Rating', value: 'rating' }, |
||||||
|
]; |
||||||
|
|
||||||
|
type SortProjectsProps = { |
||||||
|
selectedSort: string; |
||||||
|
onSelectSort: (sort: string) => void; |
||||||
|
}; |
||||||
|
|
||||||
|
export function SortProjects(props: SortProjectsProps) { |
||||||
|
const { selectedSort, onSelectSort } = props; |
||||||
|
const [isOpen, setIsOpen] = useState(false); |
||||||
|
const dropdownRef = useRef<HTMLDivElement>(null); |
||||||
|
|
||||||
|
useOutsideClick(dropdownRef, () => { |
||||||
|
setIsOpen(false); |
||||||
|
}); |
||||||
|
|
||||||
|
const selectedOption = |
||||||
|
sortOptions.find((option) => option.value === selectedSort) || |
||||||
|
sortOptions[0]; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="relative flex-shrink-0" ref={dropdownRef}> |
||||||
|
<button |
||||||
|
className="flex items-center gap-1 rounded-md border border-gray-300 py-1.5 pl-3 pr-2 text-xs font-medium text-gray-900" |
||||||
|
onClick={() => setIsOpen(!isOpen)} |
||||||
|
> |
||||||
|
{selectedOption.label} |
||||||
|
<ChevronDown className="ml-1 h-4 w-4" /> |
||||||
|
</button> |
||||||
|
|
||||||
|
{isOpen && ( |
||||||
|
<div className="absolute right-0 top-full z-10 mt-1.5 min-w-[150px] overflow-hidden rounded-md border border-gray-300 bg-white shadow-lg"> |
||||||
|
<div className="py-1"> |
||||||
|
{sortOptions.map((option) => ( |
||||||
|
<button |
||||||
|
key={option.value} |
||||||
|
className={`flex w-full items-center px-4 py-1.5 text-left text-sm text-gray-700 hover:bg-gray-100 ${ |
||||||
|
selectedSort === option.value ? 'bg-gray-100' : '' |
||||||
|
}`}
|
||||||
|
onClick={() => { |
||||||
|
onSelectSort(option.value); |
||||||
|
setIsOpen(false); |
||||||
|
}} |
||||||
|
> |
||||||
|
{option.label} |
||||||
|
</button> |
||||||
|
))} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
Loading…
Reference in new issue