feat: like button animation
This commit is contained in:
parent
e17b3908ae
commit
a2ea5f6aec
2 changed files with 42 additions and 3 deletions
|
|
@ -1,5 +1,24 @@
|
||||||
@import "tailwindcss";
|
@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 {
|
body {
|
||||||
@apply bg-amber-50;
|
@apply bg-amber-50;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon, loadIcons } from "@iconify/react";
|
||||||
import { abbreviateNumber } from "@/lib/abbreviation";
|
import { abbreviateNumber } from "@/lib/abbreviation";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -18,6 +18,7 @@ interface Props {
|
||||||
export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, disabled, abbreviate, big }: Props) {
|
export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, disabled, abbreviate, big }: Props) {
|
||||||
const [isLikedState, setIsLikedState] = useState(isLiked);
|
const [isLikedState, setIsLikedState] = useState(isLiked);
|
||||||
const [likesState, setLikesState] = useState(likes);
|
const [likesState, setLikesState] = useState(likes);
|
||||||
|
const [isAnimating, setIsAnimating] = useState(false);
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
|
|
@ -26,6 +27,12 @@ export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, disabled
|
||||||
setIsLikedState(!isLikedState);
|
setIsLikedState(!isLikedState);
|
||||||
setLikesState(isLikedState ? likesState - 1 : likesState + 1);
|
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" });
|
const response = await fetch(`/api/mii/${miiId}/like`, { method: "PATCH" });
|
||||||
|
|
||||||
if (response.ok) {
|
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 (
|
return (
|
||||||
<button onClick={onClick} className={`flex items-center gap-2 text-red-400 ${disabled ? "" : "cursor-pointer"} ${big ? "text-3xl" : "text-xl"}`}>
|
<button onClick={onClick} className={`flex items-center gap-2 text-red-400 ${disabled ? "" : "cursor-pointer"} ${big ? "text-3xl" : "text-xl"}`}>
|
||||||
<Icon icon={isLikedState ? "icon-park-solid:like" : "icon-park-outline:like"} />
|
<div className="relative">
|
||||||
|
<Icon icon={isLikedState ? "icon-park-solid:like" : "icon-park-outline:like"} className={`${isAnimating ? "animate-like " : ""}`} />
|
||||||
|
<div
|
||||||
|
className={`absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 size-6 rounded-full bg-red-400/0 ${
|
||||||
|
isAnimating ? "bg-red-400/40 animate-ping" : ""
|
||||||
|
}`}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<span>{abbreviate ? abbreviateNumber(likesState) : likesState}</span>
|
<span>{abbreviate ? abbreviateNumber(likesState) : likesState}</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue