Animates text by gradually turning blurry letters into clear ones, word or letter by letter.
import TextEmergeAnimation from "@/registry/text-effects/text-emerge-animation/text-emerge-animation";
const TextEmergeAnimationPreview = () => {
return (
<TextEmergeAnimation
className="text-gray-900 dark:text-gray-100 text-xl overflow-hidden px-5 max-w-xl"
text="A subtle motion to guide your attention. Nothing loud, nothing distracting — just a quiet transition that makes the interface feel alive.
Good animation isn't decoration; it's a gentle cue that helps you understand where you are and what happens next."
stagger={0.02}
/>
)
};
export default TextEmergeAnimationPreview; Install the following packages before using this component.
import { memo, useMemo } from "react";
import { motion } from "motion/react";
export type TextEmergeAnimationProps = {
text: string;
unit?: "word" | "letter",
stagger?: number;
delay?: number;
className?: string;
} & React.ComponentProps<"span">;
const TextEmergeAnimation = (
props: TextEmergeAnimationProps
) => {
const {
text = "",
unit = "word",
stagger = 0.1,
delay = 0,
className,
...restProps
} = props;
const textMapping = useMemo(() => (
text
.split(" ")
.filter(Boolean)
.map(word => {
if (unit === "word") {
return [word, " "];
} else {
return [
...word
.split("")
.filter(Boolean),
" "
];
}
})
.flat()
), [text, unit]);
return (
<span
{...restProps}
className={className}
>
{textMapping.map((entry, entryIndex) => (
<motion.span
key={`text-${entryIndex}`}
className="inline-block"
aria-hidden={true}
animate={{
opacity: 1,
filter: "blur(0px)",
y: 0,
}}
style={{
opacity: 0,
filter: "blur(20px)",
y: 10,
}}
transition={{
ease: "easeInOut",
duration: 0.5,
delay: entryIndex * stagger,
}}
>
{entry === " " ? <> </> : entry}
</motion.span>
))}
<span className="sr-only">
{text}
</span>
</span>
)
};
export default memo(TextEmergeAnimation); | Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| text | string | Yes | — | The text to display. Can be a word, sentence, or paragraph depending on type. |
| type | "word" | "letter" | No | "word" | Determines the animation unit: "word" animates one word at a time, "letter" animates each letter individually. |
| stagger | number | No | 0.1 | Time delay between each animated unit (in seconds). |
| className | string | No | — | Optional class name applied to the root container. |
If you find this component useful, consider starring the repository on GitHub. Found a bug or have a suggestion? Open an issue to help improve it.