UIStudio Pro is live - modern UI, powerful animations, zero hassle.
Components
Text Hover

Text Hover

Interactive text effect with layered shadows, particles, and smooth animations on hover.

UI STUDIO

UI STUDIO

UI STUDIO

Installation

1

Install the packages

npm i motion clsx tailwind-merge
2

Add util file

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

Copy and paste the following code into your project

text-hover.tsx
"use client"; import React, { useState } from "react"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export function TextHover() { const [isHovered, setIsHovered] = useState(false); const text = "UI STUDIO"; return ( <div className="h-[40rem] flex items-center justify-center bg-slate-50 dark:bg-slate-950"> <div className="relative cursor-pointer" onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {/* Main text */} <motion.h1 className="text-6xl md:text-8xl lg:text-9xl font-black text-slate-900 dark:text-slate-100 select-none" animate={{ scale: isHovered ? 1.05 : 1, }} transition={{ duration: 0.3, ease: "easeOut" }} > {text.split("").map((letter, index) => ( <motion.span key={index} className="inline-block" animate={{ y: isHovered ? Math.sin(index * 0.5) * 10 : 0, color: isHovered ? "#64748b" : undefined, }} transition={{ duration: 0.4, delay: isHovered ? index * 0.05 : 0, ease: "easeOut", }} > {letter === " " ? "\u00A0" : letter} </motion.span> ))} </motion.h1> {/* Shadow text */} <motion.h1 className="absolute inset-0 text-6xl md:text-8xl lg:text-9xl font-black text-slate-400 dark:text-slate-600 select-none -z-10" animate={{ x: isHovered ? 8 : 0, y: isHovered ? 8 : 0, opacity: isHovered ? 0.5 : 0, }} transition={{ duration: 0.3, ease: "easeOut" }} > {text} </motion.h1> {/* Outline text */} <motion.h1 className="absolute inset-0 text-6xl md:text-8xl lg:text-9xl font-black select-none" style={{ WebkitTextStroke: "2px #64748b", WebkitTextFillColor: "transparent", }} animate={{ x: isHovered ? -4 : 0, y: isHovered ? -4 : 0, opacity: isHovered ? 0.8 : 0, }} transition={{ duration: 0.3, ease: "easeOut" }} > {text} </motion.h1> {/* Particles on hover */} {isHovered && Array.from({ length: 15 }).map((_, i) => ( <motion.div key={i} className="absolute w-2 h-2 bg-slate-500 rounded-full" style={{ left: `${Math.random() * 100}%`, top: `${Math.random() * 100}%`, }} initial={{ opacity: 0, scale: 0 }} animate={{ opacity: [0, 1, 0], scale: [0, 1, 0], x: [0, (Math.random() - 0.5) * 100], y: [0, (Math.random() - 0.5) * 100], }} transition={{ duration: 1.5, ease: "easeOut", delay: Math.random() * 0.5, }} /> ))} {/* Background glow */} <motion.div className="absolute inset-0 bg-gradient-radial from-slate-300/20 to-transparent rounded-full blur-3xl -z-20" animate={{ scale: isHovered ? 1.5 : 0, opacity: isHovered ? 1 : 0, }} transition={{ duration: 0.5, ease: "easeOut" }} /> </div> </div> ); } export default TextHover;
4

Update the import paths to match your project setup

Props

PropTypeDefaultDescription
textstringUI STUDIOThe text to display with hover effects.
classNamestringAdditional CSS classes for the text hover container.