trptk/components/cart/CartButton.tsx
2026-02-24 17:14:07 +01:00

60 lines
1.8 KiB
TypeScript

"use client";
import { useRef } from "react";
import { motion } from "framer-motion";
import { IoCartOutline } from "react-icons/io5";
import { IconButton } from "@/components/IconButton";
import { useCart } from "./CartContext";
export function CartButton({ className }: { className?: string }) {
const { itemCount, setDrawerOpen } = useCart();
const hasItems = itemCount > 0;
// If the component mounts with items already in the cart (e.g. navigating
// between pages), start fully visible so there's no fade-in on every page.
const mountedWithItems = useRef(hasItems);
return (
<motion.div
className={className}
initial={{
opacity: mountedWithItems.current ? 1 : 0,
display: mountedWithItems.current ? "block" : "none",
}}
animate={
hasItems
? {
opacity: 1,
display: "block",
transition: {
type: "tween",
ease: "easeInOut",
duration: 0.2,
delay: 0.4,
},
}
: {
opacity: 0,
transition: {
type: "tween",
ease: "easeInOut",
duration: 0.2,
},
transitionEnd: {
display: "none",
},
}
}
style={{ pointerEvents: hasItems ? "auto" : "none" }}
>
<IconButton onClick={() => setDrawerOpen(true)} aria-label="Open cart" className="text-lg">
<span className="relative">
<IoCartOutline />
<span className="absolute -top-1.5 -right-1.5 flex h-4 w-4 items-center justify-center rounded-full bg-trptkblue text-xs leading-none font-bold text-white dark:bg-white dark:text-lighttext">
{itemCount}
</span>
</span>
</IconButton>
</motion.div>
);
}