Polish header entrance motion
This commit is contained in:
@@ -14,6 +14,7 @@ type SiteLogoProps = {
|
||||
priority?: boolean;
|
||||
className?: string;
|
||||
replayKey?: number;
|
||||
direction?: "rtl" | "ltr";
|
||||
};
|
||||
|
||||
export function SiteLogo({
|
||||
@@ -23,11 +24,15 @@ export function SiteLogo({
|
||||
priority = false,
|
||||
className,
|
||||
replayKey = 0,
|
||||
direction = "ltr",
|
||||
}: SiteLogoProps) {
|
||||
const { theme, resolvedTheme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const controls = useAnimationControls();
|
||||
const containerControls = useAnimationControls();
|
||||
const spinControls = useAnimationControls();
|
||||
const reducedMotion = useReducedMotion();
|
||||
const directionalOffset = direction === "rtl" ? 42 : -42;
|
||||
const spinStart = direction === "rtl" ? -360 : 360;
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
@@ -38,29 +43,35 @@ export function SiteLogo({
|
||||
return;
|
||||
}
|
||||
|
||||
controls.set({
|
||||
containerControls.set({
|
||||
opacity: 0,
|
||||
x: -42,
|
||||
x: directionalOffset,
|
||||
scale: 0.88,
|
||||
rotate: -360,
|
||||
filter: "blur(8px)",
|
||||
});
|
||||
spinControls.set({ rotate: 0 });
|
||||
|
||||
void controls.start({
|
||||
void containerControls.start({
|
||||
opacity: 1,
|
||||
x: 0,
|
||||
scale: 1,
|
||||
rotate: 0,
|
||||
filter: "blur(0px)",
|
||||
transition: {
|
||||
x: { duration: 0.78, ease: [0.22, 1, 0.36, 1] },
|
||||
opacity: { duration: 0.46 },
|
||||
rotate: { duration: 0.56, ease: "easeOut" },
|
||||
scale: { duration: 0.72, ease: [0.22, 1, 0.36, 1] },
|
||||
filter: { duration: 0.42, ease: [0.22, 1, 0.36, 1] },
|
||||
},
|
||||
});
|
||||
}, [controls, reducedMotion, replayKey]);
|
||||
|
||||
void spinControls.start({
|
||||
rotate: spinStart,
|
||||
transition: {
|
||||
duration: 0.78,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
},
|
||||
});
|
||||
}, [containerControls, directionalOffset, reducedMotion, replayKey, spinControls, spinStart]);
|
||||
|
||||
const activeTheme = theme === "system" ? resolvedTheme : theme;
|
||||
const isDark = mounted && activeTheme === "dark";
|
||||
@@ -69,25 +80,32 @@ export function SiteLogo({
|
||||
|
||||
return (
|
||||
<motion.span
|
||||
className="block [transform-style:preserve-3d]"
|
||||
className="block transform-gpu [transform-style:preserve-3d]"
|
||||
initial={reducedMotion ? false : undefined}
|
||||
animate={reducedMotion ? undefined : controls}
|
||||
whileHover={{ scale: 1.05, y: -2, rotate: -2, filter: "drop-shadow(0 16px 28px rgba(15,23,42,0.14))" }}
|
||||
whileTap={{ scale: 0.9, rotate: 6, y: 1, filter: "drop-shadow(0 8px 18px rgba(15,23,42,0.18))" }}
|
||||
animate={reducedMotion ? undefined : containerControls}
|
||||
transition={{ duration: 0.32, ease: [0.22, 1, 0.36, 1] }}
|
||||
whileHover={reducedMotion ? undefined : { scale: 1.03, y: -1.5, rotate: -1.25 }}
|
||||
whileTap={reducedMotion ? undefined : { scale: 0.97, rotate: 1.5, y: 0.5 }}
|
||||
>
|
||||
<Image
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={360}
|
||||
height={92}
|
||||
sizes="(min-width: 1280px) 360px, (min-width: 1024px) 320px, (min-width: 640px) 280px, 240px"
|
||||
className={cn(
|
||||
"h-9 w-auto object-contain object-left drop-shadow-[0_10px_24px_rgba(15,23,42,0.12)] transition-[filter,opacity,transform] duration-300 ease-out sm:h-10 lg:h-11 xl:h-12",
|
||||
mounted ? "opacity-100" : "opacity-0",
|
||||
className,
|
||||
)}
|
||||
priority={priority}
|
||||
/>
|
||||
<motion.span
|
||||
className="block origin-center"
|
||||
initial={reducedMotion ? false : { rotate: 0 }}
|
||||
animate={reducedMotion ? undefined : spinControls}
|
||||
>
|
||||
<Image
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={360}
|
||||
height={92}
|
||||
sizes="240px"
|
||||
className={cn(
|
||||
"h-10 w-auto object-contain object-left drop-shadow-[0_10px_24px_rgba(15,23,42,0.12)] transition-opacity duration-300 ease-out",
|
||||
mounted ? "opacity-100" : "opacity-0",
|
||||
className,
|
||||
)}
|
||||
priority={priority}
|
||||
/>
|
||||
</motion.span>
|
||||
</motion.span>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user