Logo

dev-resources.site

for different kinds of informations.

Animated Hover Logo using Typescript, Tailwind and Framer Motion

Published at
1/13/2025
Categories
webdev
javascript
programming
frontend
Author
brokarim
Author
8 person written this
brokarim
open
Animated Hover Logo using Typescript, Tailwind and Framer Motion

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&amp;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>
  );
}


Enter fullscreen mode Exit fullscreen mode
frontend Article's
30 articles in total
Favicon
[Boost]
Favicon
๐Ÿ’ก Smarter UX, AI-Powered Design & HTML in 2025
Favicon
5 Fun Projects to Master ES6 Javascript Basics in 2025 ๐Ÿš€๐Ÿ‘จโ€๐Ÿ’ป
Favicon
POST ABOUT AI'S INCREASING INFLUENCE IN CODING
Favicon
Truncating Text with Text-Overflow
Favicon
5 Tools Every Developer Should Know in 2025
Favicon
Checkout the new @defer in Angular
Favicon
Speed Up Your Frontend Development 10x with These Mock Tools ๐Ÿš€
Favicon
Animated Select component using typescript, shadcn and framer-motion
Favicon
[Boost]
Favicon
Deferred loading with @defer: Optimize Your App's Performance
Favicon
Understanding React's useState with Callback Functions: A Deep Dive
Favicon
Hello World from Anti-chaos
Favicon
ๅพฎๅ‰็ซฏ
Favicon
How to improve the Frontend part of the project using one button as an example :))))
Favicon
Things About Contexts in Front-end Projects
Favicon
37 Tip dร nh cho sแปฑ nghiแป‡p cแปงa Frontend Develop (P1)
Favicon
How to Load Remote Components in Vue 3
Favicon
Emotional Resilience: A Key to Success Across Fields
Favicon
Middlewares: O que sรฃo e como utilizar no Nuxt.JS
Favicon
Recreating the Interswitch Homepage with React and TailwindCSS.
Favicon
Create Stunning Gradual Div Reveals with JavaScript setTimeout and CSS Transitions
Favicon
Master GrapesJS: Build Stunning Web Pages and Seamlessly Integrate Grapes Studio SDK
Favicon
Magic of Axios Interceptors: A Deep Dive
Favicon
The Ultimate Guide to Trusting QuickBooks in Your Browser for Business Efficiency
Favicon
8 Common Front-End Developer Interview Questions For 2025
Favicon
[Boost]
Favicon
The System of UI Components in Front-end Projects
Favicon
Transform Your Web Development Workflow with These JavaScript Giants
Favicon
Animated Hover Logo using Typescript, Tailwind and Framer Motion

Featured ones: