nexus-labs
componentanimated-select-headlinesource: ok · hit
Animated Select Headline
A cycling word headline where each active word is highlighted with a Figma-style selection rectangle — thin border with corner handles — using blur-fade transitions.
npx shadcn add "https://nexus-ui.com/r/animated-select-headline.json"free
Visual style
glass-blur
Interaction
dropdown
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · mediumanimationframer-motion
Registry dependencies
https://www.nexus-ui.com/api/registry/nexus-fontutils
Files2 · source cached 10/9/2026, 12:05:14 PM
next-ui/animated-select-headline/animated-select-headline.tsx
"use client";
import { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "@/lib/utils";
export interface AnimatedSelectHeadlineProps {
words?: string[];
prefix?: string;
suffix?: string;
interval?: number;
className?: string;
headingClassName?: string;
}
const ACCENT_GRADIENTS = [
"bg-gradient-to-r from-cyan-400 to-emerald-500 bg-clip-text text-transparent",
"bg-gradient-to-r from-amber-400 to-pink-500 bg-clip-text text-transparent",
];
export function AnimatedSelectHeadline({
words = ["warp speed", "pure flow", "light speed"],
prefix = "Build amazing websites at",
suffix,
interval = 2500,
className,
headingClassName,
}: AnimatedSelectHeadlineProps) {
const [index, setIndex] = useState(0);
useEffect(() => {
const id = setInterval(
() => setIndex((i) => (i + 1) % words.length),
interval,
);
return () => clearInterval(id);
}, [words.length, interval]);
// Last two words get an accent color treatment.
const accentStart = Math.max(words.length - 2, 0);
const isAccent = index >= accentStart;
const accentClass = isAccent
? ACCENT_GRADIENTS[index - accentStart]
: undefined;
return (
<div className={cn("text-center", className)}>
<h2
className={cn(
"text-4xl font-bold leading-tight tracking-tight text-gray-950 sm:text-5xl",
headingClassName,
)}
>
{prefix && <>{prefix} </>}
<AnimatePresence mode="wait">
<motion.span
key={index}
initial={{ opacity: 0, filter: "blur(8px)", y: 8 }}
animate={{ opacity: 1, filter: "blur(0px)", y: 0 }}
exit={{ opacity: 0, filter: "blur(8px)", y: -8 }}
transition={{ duration: 0.3, ease: "easeOut" }}
className={cn("relative inline-block font-bold", accentClass)}
>
{words[index]}
</motion.span>
</AnimatePresence>
{suffix && <> {suffix}</>}
</h2>
</div>
);
}
next-ui/animated-select-headline/index.ts
export { AnimatedSelectHeadline } from "./animated-select-headline";
export type { AnimatedSelectHeadlineProps } from "./animated-select-headline";