web-mikul-news/components/landing-page/option.tsx

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;