import { useEffect, useRef } from 'react';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import { useReducedMotion } from '#/lib/browser/reduced-motion';
import * as styles from '#/components/PostControls/AnimatedLikeIcon.css';
import HeartIconFilled from '#/icons/central/Heart2_round_filled_radius1_stroke2.svg';
import HeartIconOutline from '#/icons/central/Heart2_round_outlined_radius1_stroke2.svg';
const animationConfig: KeyframeAnimationOptions = {
duration: 600,
easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
fill: 'forwards',
};
const scaleKeyframes: Keyframe[] = [
{ transform: 'scale(1)' },
{ transform: 'scale(0.7)' },
{ transform: 'scale(1.2)' },
{ transform: 'scale(1)' },
];
const circle1Keyframes: Keyframe[] = [
{ opacity: 0, transform: 'scale(0)' },
{ opacity: 0.4 },
{ transform: 'scale(1.5)' },
{ opacity: 0.4 },
{ opacity: 0, transform: 'scale(1.5)' },
];
const circle2Keyframes: Keyframe[] = [
{ opacity: 0, transform: 'scale(0)' },
{ opacity: 1 },
{ transform: 'scale(0)' },
{ opacity: 1 },
{ opacity: 0, transform: 'scale(1.5)' },
];
export function AnimatedLikeIcon({
size = 18,
isLiked,
hasBeenToggled,
}: {
size?: number;
isLiked: boolean;
hasBeenToggled: boolean;
}) {
const reducedMotion = useReducedMotion();
const shouldAnimate = hasBeenToggled && !reducedMotion;
const prevIsLiked = useRef(isLiked);
const heartRef = useRef<SVGSVGElement>(null);
const circle1Ref = useRef<HTMLDivElement>(null);
const circle2Ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (prevIsLiked.current === isLiked) {
return;
}
prevIsLiked.current = isLiked;
if (shouldAnimate && isLiked) {
heartRef.current?.animate(scaleKeyframes, animationConfig);
circle1Ref.current?.animate(circle1Keyframes, animationConfig);
circle2Ref.current?.animate(circle2Keyframes, animationConfig);
}
}, [shouldAnimate, isLiked]);
return (
<div className={styles.root} style={assignInlineVars({ [styles.sizeVar]: `${size}px` })}>
{isLiked ? (
<HeartIconFilled ref={heartRef} className={styles.heart} />
) : (
<HeartIconOutline className={styles.heart} />
)}
<div ref={circle1Ref} className={styles.circle1} />
<div ref={circle2Ref} className={styles.circle2} />
</div>
);
}