Spaces:
Paused
Paused
import React, { ReactNode, useEffect, useRef, useState } from "react"; | |
import { motion, Variants } from "framer-motion"; | |
import useOutsideRef from "../hooks/useOutsideRef"; | |
import Router from "next/router"; | |
import { useAppSelector } from "../store/hook"; | |
import { theme_state } from "../store/features/themeSlice"; | |
interface DropdownProps { | |
trigger: ReactNode; | |
children: ReactNode; | |
classname: string; | |
} | |
export const Dropdown = ({ trigger, children, classname }: DropdownProps) => { | |
const [isOpen, setIsOpen] = useState(false); | |
const dropdownRef = useRef(null); | |
const { theme } = useAppSelector(theme_state); | |
const { isOutsideRef } = useOutsideRef(dropdownRef); | |
useEffect(() => { | |
if (isOutsideRef) { | |
setIsOpen(false); | |
} | |
}, [isOutsideRef]); | |
const toggleMenu = () => { | |
setIsOpen(!isOpen); | |
}; | |
Router.events.on("routeChangeStart", () => { | |
setIsOpen(false); | |
}); | |
const animation: Variants = { | |
enter: { | |
opacity: 1, | |
scale: 1, | |
transformOrigin: "top right", | |
transition: { | |
duration: 0.25, | |
}, | |
display: "block", | |
}, | |
exit: { | |
opacity: 0, | |
scale: 0.7, | |
transformOrigin: "top right", | |
transition: { | |
duration: 0.2, | |
delay: 0.1, | |
}, | |
transitionEnd: { | |
display: "none", | |
}, | |
}, | |
}; | |
return ( | |
<div ref={dropdownRef}> | |
<motion.div className="menu-item relative"> | |
<div className="cursor-pointer" onClick={toggleMenu}> | |
{trigger} | |
</div> | |
<motion.div | |
className={`${classname} absolute shadow rounded-lg z-50 mt-3 glassmorphism`} | |
initial="exit" | |
animate={isOpen ? "enter" : "exit"} | |
variants={animation} | |
> | |
<div>{children}</div> | |
</motion.div> | |
</motion.div> | |
</div> | |
); | |
}; | |