Animated Links

A captivating animated link component that creates a mesmerizing character-by-character hover effect with smooth staggered animations. Perfect for adding to your socials,menus etc.

Install dependencies

npm i clsx tailwind-merge motion

Add utility file

lib/utils.ts

import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Code

AnimatedLinks.tsx


"use client"
import { motion } from "framer-motion"
import { cn } from "@/lib/utils"

interface StaggerLinkProps {
  text: string
  href?: string
  className?: string
  duration?: number
  stagger?: number
}

const AnimatedLinks = ({ text, href = "#", className, duration = 0.25, stagger = 0.025 }: StaggerLinkProps) => {
  const safeText = typeof text === "string" ? text : String(text || "")

  return (
    <motion.a
      href={href}
      initial="initial"
      whileHover="hovered"
      style={{ lineHeight: 0.75 }}
      className={cn(
        "relative block overflow-hidden whitespace-nowrap text-xl sm:text-xl md:text-2xl lg:text-3xl text-neutral-200",
        className,
      )}
    >
     
      <div className="flex space-x-0 leading-none">
        {safeText.split("").map((char, i) => (
          <motion.span
            key={i}
            className="inline-block"
            variants={{
              initial: { y: 0 },
              hovered: { y: "-100%" },
            }}
            transition={{
              duration,
              ease: "easeInOut",
              delay: stagger * i,
            }}
          >
             {char === " " ? "\u00A0" : char}
          </motion.span>
        ))}
      </div>

    
      <div className="absolute inset-0 flex space-x-0 leading-none">
        {safeText.split("").map((char, i) => (
          <motion.span
            key={i}
            className="inline-block"
            variants={{
              initial: { y: "100%" },
              hovered: { y: 0 },
            }}
            transition={{
              duration,
              ease: "easeInOut",
              delay: stagger * i,
            }}
          >
           {char === " " ? "\u00A0" : char}
          </motion.span>
        ))}
      </div>
    </motion.a>
  )
}

export default AnimatedLinks

Props

PropTypeDefaultDescription
textstring-The text content to display and animate
hrefstring"#"The URL to navigate to when clicked
classNamestring-Additional CSS classes for custom styling
durationnumber0.25Animation duration in seconds for each character
staggernumber0.025Delay between each character's animation start
Animated-Links16