Add the same badge pulse animation to the wishlist icon as the cart icon
Same mount-guard pattern as CartLink's own pulse fix — useWishlist()'s count only fills in after its client-side fetch resolves, so without the guard this would have pulsed on every page load too, not just a real add/remove during the session. Fires on either direction (add or remove) since the wishlist has no separate "flying" animation like the cart's ball-to-icon effect to lean on instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018unaXmuzVA8ct1b6WoyP1U
This commit is contained in:
@@ -142,6 +142,28 @@ function AccountLink() {
|
||||
// to 320px that this fits without wrapping/overflow (see git history).
|
||||
function WishlistLink() {
|
||||
const { count } = useWishlist();
|
||||
const [pulse, setPulse] = useState(false);
|
||||
const prevCountRef = useRef(0);
|
||||
// Same guard as CartLink's own — useWishlist() starts from an empty
|
||||
// cached/SSR-safe list and only fills in the real count once its own
|
||||
// fetch resolves client-side, so without this the badge pulsed on every
|
||||
// page load/reload the instant that first real count arrived, not just
|
||||
// on an actual add/remove during the session.
|
||||
const hasMountedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasMountedRef.current) {
|
||||
hasMountedRef.current = true;
|
||||
prevCountRef.current = count;
|
||||
return;
|
||||
}
|
||||
if (count !== prevCountRef.current) {
|
||||
setPulse(true);
|
||||
const t = setTimeout(() => setPulse(false), 350);
|
||||
prevCountRef.current = count;
|
||||
return () => clearTimeout(t);
|
||||
}
|
||||
}, [count]);
|
||||
|
||||
return (
|
||||
<Link
|
||||
@@ -149,7 +171,12 @@ function WishlistLink() {
|
||||
aria-label={count > 0 ? `Merkliste, ${count} Artikel` : "Merkliste"}
|
||||
className="relative flex h-11 w-11 items-center justify-center shrink-0 active:scale-[0.9] transition-transform"
|
||||
>
|
||||
<svg viewBox="0 0 20 18" className="h-6 w-6 text-text-primary" fill="none" aria-hidden="true">
|
||||
<svg
|
||||
viewBox="0 0 20 18"
|
||||
className={"h-6 w-6 text-text-primary transition-transform duration-300 " + (pulse ? "scale-110" : "scale-100")}
|
||||
fill="none"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
d="M10 17S1 11.5 1 5.8C1 2.6 3.4 1 5.8 1c1.6 0 3.2.9 4.2 2.4C11 1.9 12.6 1 14.2 1 16.6 1 19 2.6 19 5.8 19 11.5 10 17 10 17Z"
|
||||
stroke="currentColor"
|
||||
@@ -158,7 +185,12 @@ function WishlistLink() {
|
||||
/>
|
||||
</svg>
|
||||
{count > 0 && (
|
||||
<span className="absolute top-0 right-0 flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-brand px-1 text-[0.6875rem] font-bold leading-none text-white">
|
||||
<span
|
||||
className={
|
||||
"absolute top-0 right-0 flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-brand px-1 text-[0.6875rem] font-bold leading-none text-white transition-transform duration-300 " +
|
||||
(pulse ? "scale-125" : "scale-100")
|
||||
}
|
||||
>
|
||||
{count > 99 ? "99+" : count}
|
||||
</span>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user