Animated Hero
A stunning animated hero section with a rainbow aurora background, glassmorphic text effects, and optional theme toggle.
Install using CLI
npx shadcn@latest add "https://vengeance-ui.vercel.app/r/animated-hero.json"Install Manually
Install dependencies
npm install clsx tailwind-merge framer-motion lucide-react
Add util file
lib/utils.ts
import { ClassValue, clsx } from "clsx";import { twMerge } from "tailwind-merge";export function cn(...inputs: ClassValue[]) {return twMerge(clsx(inputs));}
Add styles to global CSS
Add the following CSS variables and animations to your app/globals.css file
/* Add to :root */:root {--rainbow-blue: 217 91% 60%;--rainbow-pink: 330 81% 60%;--rainbow-cyan: 180 77% 50%;--stripe-color: rgba(255, 255, 255, 0.1);}.dark {--stripe-color: rgba(0, 0, 0, 0.3);}/* Animations */@keyframes aurora-bg {0% { background-position: 0% 50%, 0% 50%; }50% { background-position: 100% 50%, 100% 50%; }100% { background-position: 0% 50%, 0% 50%; }}@keyframes aurora-blink {0%, 100% { opacity: 1; }50% { opacity: 0.3; }}.animate-aurora-bg {animation: aurora-bg 15s ease infinite;}.animate-aurora-blink {animation: aurora-blink 2s ease-in-out infinite;}
Copy the source code
Copy the code below and paste it into components/ui/animated-hero.tsx
"use client";import { useEffect, useState } from "react";import { motion } from "framer-motion";import { Sun, Moon } from "lucide-react";import { cn } from "@/lib/utils";interface AnimatedHeroProps {/** Hero title text */title?: string;/** Whether to show the theme toggle button */showThemeToggle?: boolean;/** Additional CSS classes */className?: string;}export function AnimatedHero({title = "AN AWESOME TITLE",showThemeToggle = true,className = "",}: AnimatedHeroProps) {const [isDark, setIsDark] = useState(false);const [mounted, setMounted] = useState(false);useEffect(() => {setMounted(true);const checkDarkMode = () => {return document.documentElement.classList.contains("dark");};setIsDark(checkDarkMode());const observer = new MutationObserver((mutations) => {mutations.forEach((mutation) => {if (mutation.attributeName === "class") {setIsDark(checkDarkMode());}});});observer.observe(document.documentElement, {attributes: true,attributeFilter: ["class"],});return () => observer.disconnect();}, []);const toggleTheme = () => {document.documentElement.classList.toggle("dark");};if (!mounted) {return null;}return (<section className={cn("relative w-full h-auto", className)}>{/* Animated Background */}<divclassName="relative w-full min-h-screen flex items-center justify-center transition-all duration-500"style={{backgroundImage: `repeating-linear-gradient(100deg,var(--stripe-color) 0%,var(--stripe-color) 7%,transparent 10%,transparent 12%,var(--stripe-color) 16%),repeating-linear-gradient(100deg,hsl(var(--rainbow-blue)) 10%,hsl(var(--rainbow-pink)) 15%,hsl(var(--rainbow-blue)) 20%,hsl(var(--rainbow-cyan)) 25%,hsl(var(--rainbow-blue)) 30%)`,backgroundSize: "300%, 200%",backgroundPosition: "50% 50%, 50% 50%",filter: isDark? "blur(10px) opacity(0.5) saturate(2)": "blur(10px) invert(1)",maskImage:"radial-gradient(ellipse at 100% 0%, black 40%, transparent 70%)",WebkitMaskImage:"radial-gradient(ellipse at 100% 0%, black 40%, transparent 70%)",}}><divclassName="absolute inset-0 animate-aurora-bg"style={{backgroundImage: `repeating-linear-gradient(100deg,var(--stripe-color) 0%,var(--stripe-color) 7%,transparent 10%,transparent 12%,var(--stripe-color) 16%),repeating-linear-gradient(100deg,hsl(var(--rainbow-blue)) 10%,hsl(var(--rainbow-pink)) 15%,hsl(var(--rainbow-blue)) 20%,hsl(var(--rainbow-cyan)) 25%,hsl(var(--rainbow-blue)) 30%)`,backgroundSize: "200%, 100%",backgroundAttachment: "fixed",mixBlendMode: "difference",}}/></div>{/* Content */}<divclassName="absolute inset-0 flex flex-col items-center justify-center gap-8 text-center px-4"style={{mixBlendMode: "difference",filter: "invert(1)",}}><motion.h1initial={{ opacity: 0, y: 20 }}animate={{ opacity: 1, y: 0 }}transition={{ duration: 0.8, ease: "easeOut" }}className="text-[clamp(2rem,1rem+5vw,8rem)] font-black relative leading-tight tracking-tight"data-text={title}><span className="relative z-0">{title}</span><spanclassName="absolute inset-0 flex items-center justify-center pointer-events-none z-10"style={{background: "white",textShadow: "0 0 1px #ffffff",backgroundClip: "text",WebkitBackgroundClip: "text",WebkitTextFillColor: "transparent",backgroundColor: "white",WebkitMask: "linear-gradient(#000 0 0) luminance",mask: "linear-gradient(#000 0 0) luminance, alpha",backdropFilter: "blur(19px) brightness(12.5)",WebkitBackdropFilter: "blur(19px) brightness(12.5)",WebkitTextStroke: "1px white",}}>{title}</span></motion.h1>{showThemeToggle && (<motion.buttoninitial={{ opacity: 0, scale: 0.8 }}animate={{ opacity: 1, scale: 1 }}transition={{ duration: 0.5, delay: 0.3 }}whileHover={{ scale: 1.1 }}whileTap={{ scale: 0.95 }}onClick={toggleTheme}className="group cursor-pointer p-3 rounded-full border border-dashed hover:border-solid transition-all"aria-label="Toggle theme"><motion.divinitial={false}animate={{ rotate: isDark ? 180 : 0 }}transition={{ duration: 0.3 }}>{isDark ? (<Sun className="w-6 h-6 animate-aurora-blink group-hover:[animation-play-state:paused]" />) : (<Moon className="w-6 h-6 animate-aurora-blink group-hover:[animation-play-state:paused]" />)}</motion.div></motion.button>)}</div></section>);}export default AnimatedHero;
Usage
1import { AnimatedHero } from "@/components/ui/animated-hero"23export function HeroPage() {4return (5 <AnimatedHero title="WELCOME" />6);7}
Examples
Custom Title
Without Theme Toggle
With Custom Class
Props
| Prop Name | Type | Default | Description |
|---|---|---|---|
| title | string | "AN AWESOME TITLE" | The hero title text to display. |
| showThemeToggle | boolean | true | Whether to show the theme toggle button. |
| className | string | "" | Additional CSS classes for the section. |
Features
Aurora Background: Mesmerizing rainbow gradient animation
Glassmorphic Text: Stunning text effect with blur and transparency
Theme Toggle: Built-in dark/light mode toggle with animation
Responsive Typography: Text scales beautifully across screen sizes
Smooth Animations: Framer Motion powered entrance animations
Dark Mode Support: Automatically adapts background effects
Extra Bold Text: Uses font-black for maximum impact
Customizable: Easy to customize title and toggle visibility