HomeComponentHover Button One

Hover Button one

Published Nov 20, 2024
By Vishal Karangale
Framer Motion
tailwindCss

Component Props


Required Props

PropTypeDefault
className
string
-

Optional Props

PropTypeDefault
className
string
-

Base Component

Copy and paste the following base component in your project
Make sure to install all the required dependencies

HoverButton.tsx
"use client";
 
import { motion } from "framer-motion";
import { useState } from "react";
import { twMerge } from "tailwind-merge";
 
interface HoverButtonProps {
  expandText: string;
  buttonText: string;
  icon: string | JSX.Element;
}
 
const HoverButton: React.FC<HoverButtonProps> = ({
  buttonText,
  icon,
  expandText,
}) => {
  const [expand, setExapnd] = useState(false);
  return (
    <motion.button
      layout
      onHoverStart={() => setExapnd(true)}
      onHoverEnd={() => setExapnd(false)}
      className="flex w-56 items-center gap-2 overflow-hidden rounded-full bg-white-a12 p-1"
    >
      <motion.div layout className="flex w-full items-center">
        <motion.div
          layout
          animate={{
            width: expand ? "100%" : "40%",
            transition: { duration: 0.5, ease: "easeInOut" },
          }}
          className={twMerge(
            "flex h-full items-center justify-center gap-3 rounded-full bg-purple-600 py-2",
          )}
        >
          <motion.p
            variants={{
              initial: { opacity: 0, x: -30 },
              animate: {
                opacity: 1,
                x: 0,
                transition: { duration: 0.5, ease: "easeInOut" },
              },
            }}
            initial="initial"
            animate={expand ? "animate" : "initial"}
            transition={{ duration: 0.3, ease: "easeInOut" }}
            className={twMerge(
              "whitespace-nowrap font-semibold text-lg text-white",
              expand ? "block" : "hidden",
            )}
          >
            {expandText}
          </motion.p>
          <motion.div layout>{icon}</motion.div>
        </motion.div>
        <motion.div
          layout
          animate={{
            width: expand ? "0%" : "60%",
            padding: expand ? "0px" : "6px",
            transition: { duration: 0.5, ease: "easeInOut" },
          }}
          className={twMerge(
            "flex items-center justify-center rounded-full bg-white py-2.5 text-black-a12",
            !expand && "mx-1 px-2",
          )}
        >
          <motion.h1
            variants={{
              initial: { x: -20, opacity: 0 },
              animate: {
                x: 0,
                opacity: 1,
                transition: { duration: 0.5, ease: "easeInOut" },
              },
              exit: {
                opacity: [1, 0.2, 0],
                x: 30,
                transition: { duration: 0.5, ease: "easeInOut" },
              },
            }}
            initial="initial"
            animate={expand ? "exit" : "animate"}
            transition={{ duration: 0.1, ease: "easeInOut" }}
            className="relative font-semibold text-black-a12 "
          >
            {buttonText}
          </motion.h1>
        </motion.div>
      </motion.div>
    </motion.button>
  );
};
 
export default HoverButton;
Built with Next.js