It transforms a static logo into a button, which activates a video tooltip that follows the cursor's movement along the button's axis using motion values.
Upon closer inspection, you'll notice we use micro-animations. When the logo is hovered over, it smoothly scales down and fades out, then transitions into a button that scales up with a fade-in effect. Hovering over the button then triggers a video tooltip.
Demo
Source Code
logo-hover.tsx
import { useState, useCallback } from "react";
import { motion, AnimatePresence, useMotionValue } from "framer-motion";
import { Play } from "lucide-react";
export default function LogoHover() {
const [isHovered, setIsHovered] = useState(false);
const [showVideo, setShowVideo] = useState(false);
const x = useMotionValue(0);
const handleMouseMove = useCallback(
(event: React.MouseEvent<HTMLElement>) => {
const halfWidth = event.currentTarget.offsetWidth / 2;
x.set(event.nativeEvent.offsetX - halfWidth);
},
[x]
);
return (
<div className="relative w-[100px] h-[80px] cursor-pointer" onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
<AnimatePresence>
{!isHovered && (
// change with your own logo
<motion.img src="/theo-logo.png" alt="Wegic Logo" className="absolute inset-0 w-full h-full object-contain" initial={{ opacity: 1, scale: 1 }} exit={{ opacity: 0, scale: 0.8 }} transition={{ duration: 0.2 }} />
)}
</AnimatePresence>
<AnimatePresence>
{isHovered && (
<motion.div className="absolute inset-0 flex items-center justify-center w-full" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0, scale: 0.8 }} transition={{ duration: 0.2 }}>
<button
className="flex w-full items-center justify-center gap-2 bg-white border border-black h-10 py-2 rounded-md"
onMouseMove={handleMouseMove}
onMouseEnter={() => setShowVideo(true)}
onMouseLeave={() => setShowVideo(false)}
>
<Play size={16} fill="white" strokeWidth={2} aria-hidden="true" />
<p className="text-[10px] flex font-semibold">watch video</p>
</button>
</motion.div>
)}
</AnimatePresence>
{/* Video Tooltip */}
<AnimatePresence mode="popLayout">
{showVideo && (
<motion.div
initial={{ opacity: 0, y: 20, scale: 0.6 }}
animate={{
opacity: 1,
y: 0,
scale: 1,
transition: {
stiffness: 260,
damping: 10,
duration: 0.3,
},
width: "200px",
height: "auto",
}}
exit={{ opacity: 0, y: 20, scale: 0.6 }}
style={{
translateX: x,
}}
className="absolute top-full mt-2 z-50"
>
<motion.div className="rounded-md overflow-hidden ">
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/ZK-rNEhJIDs?si=KBECTf4W-b_37Xsn&autoplay=1&mute=1&controls=0"
title="YouTube video player"
className="w-full h-full object-cover rounded-md border-[1px] border-white ring-1 ring-black/5"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen
></iframe>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</div>
);
}
Top comments (0)