feat(ui): improve MulticaIcon animation behavior

- Separate entrance animation from hover animation
- Use state to track entrance completion
- Hover spin only activates after entrance is done
- Shorten entrance animation to 0.6s

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Naiyuan Qing 2026-02-11 17:47:35 +08:00
parent d189b14a15
commit b825c6b3d8
2 changed files with 18 additions and 8 deletions

View file

@ -1,8 +1,9 @@
import { useState, useEffect } from "react";
import { cn } from "@multica/ui/lib/utils";
interface MulticaIconProps extends React.ComponentProps<"span"> {
/**
* If true, play a one-time entrance spin animation (2 seconds).
* If true, play a one-time entrance spin animation.
*/
animate?: boolean;
}
@ -17,11 +18,20 @@ export function MulticaIcon({
animate = false,
...props
}: MulticaIconProps) {
const [entranceDone, setEntranceDone] = useState(!animate);
useEffect(() => {
if (!animate) return;
const timer = setTimeout(() => setEntranceDone(true), 600);
return () => clearTimeout(timer);
}, [animate]);
return (
<span
className={cn(
"inline-block size-[1em] hover:animate-spin",
animate && "animate-welcome-spin",
"inline-block size-[1em]",
!entranceDone && "animate-entrance-spin",
entranceDone && "hover:animate-spin",
className
)}
aria-hidden="true"

View file

@ -297,13 +297,13 @@
50% { box-shadow: 0 0 0 3px oklch(0.6 0.2 250 / 0); }
}
/* Welcome page: one-time spin animation for icon */
@keyframes welcome-spin {
/* Multica icon: entrance spin */
@keyframes entrance-spin {
0% { transform: rotate(0deg); opacity: 0; }
30% { opacity: 1; }
50% { opacity: 1; }
100% { transform: rotate(360deg); opacity: 1; }
}
.animate-welcome-spin {
animation: welcome-spin 2s ease-out forwards;
.animate-entrance-spin {
animation: entrance-spin 0.6s ease-out forwards;
}