58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
import { motion } from "framer-motion";
|
|
import { useState, Dispatch, SetStateAction } from "react";
|
|
|
|
export type OptionProps = {
|
|
Icon: any;
|
|
title: string;
|
|
selected?: string;
|
|
setSelected?: Dispatch<SetStateAction<string>>;
|
|
open: boolean;
|
|
notifs?: number;
|
|
active?: boolean;
|
|
};
|
|
|
|
const Option = ({ Icon, title, selected, setSelected, open, notifs, active }: OptionProps) => {
|
|
const [hovered, setHovered] = useState(false);
|
|
const isActive = active ?? selected === title;
|
|
|
|
return (
|
|
<motion.button
|
|
layout
|
|
onClick={() => setSelected?.(title)}
|
|
onMouseEnter={() => setHovered(true)}
|
|
onMouseLeave={() => setHovered(false)}
|
|
className={`relative flex h-10 w-full items-center rounded-md transition-colors cursor-pointer ${isActive ? "bg-slate-400 text-black" : "text-black hover:bg-slate-100"}`}
|
|
>
|
|
<motion.div layout className={`h-full ${open ? "w-10 grid place-content-center text-lg" : "flex-1 grid place-items-center text-lg"}`}>
|
|
<Icon />
|
|
</motion.div>
|
|
|
|
{open && (
|
|
<motion.span layout initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.125 }} className="text-xs font-medium">
|
|
{title}
|
|
</motion.span>
|
|
)}
|
|
|
|
{!open && hovered && (
|
|
<motion.span
|
|
initial={{ opacity: 0, x: 8 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: 8 }}
|
|
transition={{ type: "spring", stiffness: 300, damping: 20 }}
|
|
className="absolute left-full ml-2 whitespace-nowrap rounded bg-slate-800 px-2 py-1 text-xs text-white shadow-md z-10"
|
|
>
|
|
{title}
|
|
</motion.span>
|
|
)}
|
|
|
|
{notifs && open && (
|
|
<motion.span initial={{ scale: 0, opacity: 0 }} animate={{ opacity: 1, scale: 1 }} style={{ y: "-50%" }} transition={{ delay: 0.5 }} className="absolute right-2 top-1/2 size-4 rounded bg-indigo-500 text-xs text-white">
|
|
{notifs}
|
|
</motion.span>
|
|
)}
|
|
</motion.button>
|
|
);
|
|
};
|
|
|
|
export default Option;
|