Files
nextjs-template/components/ui/text-generate-effect.tsx
T
asepharyana bf75d9deef feat(ui): vendor Aceternity registry components + showcase gallery
Vendor 50 Aceternity UI components into components/ui from the official
registry (ui.aceternity.com/registry/<slug>.json), adapted for this
template's stack: Tailwind v4, motion/react 13, cn util, React 19.

Add a live showcase gallery (/ui + /docs/... navigation is unchanged):
app/ui/page.tsx renders <ShowcaseGallery> with 30+ demos — 3d-pin,
aurora, background-beams, bento, card-stack, card-spotlight,
direction-aware-hover, encrypted-text, evervault-card, flip-words,
hero-highlight, hero-parallax, infinite-moving-cards, moving-border,
sparkles, tracing-beam, animated-tooltip, typewriter-effect,
placeholders-and-vanish-input and friends.

Toolchain stays zero-warning: vendored animation code is scoped in
eslint.config.mjs (react-hooks/react-compiler advisory rules, no-any,
prefer-const, no-img-element) so app code keeps a 0-error gate. typecheck,
build, 7 vitest tests and 2 test suites all green.
2026-09-20 19:10:43 +07:00

63 lines
1.4 KiB
TypeScript

"use client";
import { useEffect } from "react";
import { motion, stagger, useAnimate } from "motion/react";
import { cn } from "@/lib/utils";
export const TextGenerateEffect = ({
words,
className,
filter = true,
duration = 0.5,
}: {
words: string;
className?: string;
filter?: boolean;
duration?: number;
}) => {
const [scope, animate] = useAnimate();
const wordsArray = words.split(" ");
useEffect(() => {
animate(
"span",
{
opacity: 1,
filter: filter ? "blur(0px)" : "none",
},
{
duration: duration ? duration : 1,
delay: stagger(0.2),
}
);
}, [scope.current]);
const renderWords = () => {
return (
<motion.div ref={scope}>
{wordsArray.map((word, idx) => {
return (
<motion.span
key={word + idx}
className="text-black opacity-0 dark:text-white"
style={{
filter: filter ? "blur(10px)" : "none",
}}
>
{word}{" "}
</motion.span>
);
})}
</motion.div>
);
};
return (
<div className={cn("font-bold", className)}>
<div className="mt-4">
<div className="text-2xl leading-snug tracking-wide text-black dark:text-white">
{renderWords()}
</div>
</div>
</div>
);
};