diff --git a/src/app/globals.css b/src/app/globals.css index 837ee79..87ac32a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,5 +1,24 @@ @import "tailwindcss"; +@theme { + --animate-like: like 0.5s ease; + + @keyframes like { + 0% { + transform: scale(1); + } + 30% { + transform: scale(1.25); + } + 60% { + transform: scale(0.95); + } + 100% { + transform: scale(1); + } + } +} + body { @apply bg-amber-50; diff --git a/src/components/like-button.tsx b/src/components/like-button.tsx index e796a2d..b8050bb 100644 --- a/src/components/like-button.tsx +++ b/src/components/like-button.tsx @@ -1,8 +1,8 @@ "use client"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { redirect } from "next/navigation"; -import { Icon } from "@iconify/react"; +import { Icon, loadIcons } from "@iconify/react"; import { abbreviateNumber } from "@/lib/abbreviation"; interface Props { @@ -18,6 +18,7 @@ interface Props { export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, disabled, abbreviate, big }: Props) { const [isLikedState, setIsLikedState] = useState(isLiked); const [likesState, setLikesState] = useState(likes); + const [isAnimating, setIsAnimating] = useState(false); const onClick = async () => { if (disabled) return; @@ -26,6 +27,12 @@ export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, disabled setIsLikedState(!isLikedState); setLikesState(isLikedState ? likesState - 1 : likesState + 1); + // Trigger animation + if (!isLikedState) { + setIsAnimating(true); + setTimeout(() => setIsAnimating(false), 1000); // match animation duration + } + const response = await fetch(`/api/mii/${miiId}/like`, { method: "PATCH" }); if (response.ok) { @@ -38,9 +45,22 @@ export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, disabled } }; + // Preload like button icons + useEffect(() => { + loadIcons(["icon-park-solid:like", "icon-park-outline:like"]); + }, []); + return ( );