NEW
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
Learn more
Skip to content
Docs

Text Border Animation

Border animation below text

requires interactionhover
Loading...

Installation

CLI

pnpm dlx shadcn@latest add https://animata.design/r/text/text-border-animation.json

Manual

Run the following command

It will create a new file called text-border-animation.tsx inside the components/animata/text directory.

mkdir -p components/animata/text && touch components/animata/text/text-border-animation.tsx

Paste the code

Open the newly created file and paste the following code:

"use client";
 
import { useEffect, useState } from "react";
 
import { cn } from "@/lib/utils";
 
interface TextProps {
  /**
   * Text to display
   */
  text: string;
 
  className?: string;
}
 
export default function TextBorderAnimation({ text = "Programming", className }: TextProps) {
  const [isHoveredIn, setIsHoveredIn] = useState(false);
  const [isHoveredOut, setIsHoveredOut] = useState(false);
 
  const handleHover = () => {
    setIsHoveredIn(true);
  };
 
  const handleHoverExit = () => {
    setIsHoveredIn(false);
    setIsHoveredOut(true);
  };
 
  useEffect(() => {
    if (isHoveredOut) {
      const timer = setTimeout(() => {
        setIsHoveredOut(false);
      }, 300);
 
      return () => clearTimeout(timer);
    }
  }, [isHoveredOut]);
 
  return (
    <div
      onMouseEnter={handleHover}
      onMouseLeave={handleHoverExit}
      className="overflow-hidden"
      aria-hidden
    >
      <span className={cn("text-xl xl:text-5xl font-medium text-foreground", className)}>
        {text}
      </span>
      <div className="relative mt-1 h-1 w-full">
        <div
          className={cn(
            "absolute left-0 top-0 h-full w-full bg-yellow-500 transition-transform duration-300",
            isHoveredIn
              ? "translate-x-0 transform opacity-100"
              : "-translate-x-full transform opacity-0",
          )}
        ></div>
        <div
          className={cn(
            "absolute left-0 top-0 h-full w-full translate-x-0 transform bg-yellow-500 opacity-0 transition-transform duration-300",
            isHoveredOut && "translate-x-full opacity-100",
          )}
        ></div>
      </div>
    </div>
  );
}

Credits

Built by Aashish Katila