Writing Text
A text component that smoothly reveals content word by word.
Loading...
import { WritingText } from "@/components/core/writing-text";
export default function WritingTextExample() {
return (
<WritingText
className="text-4xl"
text="Writing Text With Effect"
spacing={9}
/>
);
}
Installation
Install the following dependencies:
npm install motionCopy and paste the following code into your project:
"use client";
import * as React from "react";
import {
motion,
useInView,
type Transition,
type UseInViewOptions,
} from "motion/react";
type WritingTextProps = Omit<React.ComponentProps<"span">, "children"> & {
transition?: Transition;
inView?: boolean;
inViewMargin?: UseInViewOptions["margin"];
inViewOnce?: boolean;
spacing?: number | string;
text: string;
};
function WritingText({
ref,
inView = false,
inViewMargin = "0px",
inViewOnce = true,
spacing = 5,
text,
transition = { type: "spring", bounce: 0, duration: 2, delay: 0.5 },
...props
}: WritingTextProps) {
const localRef = React.useRef<HTMLSpanElement>(null);
React.useImperativeHandle(ref, () => localRef.current as HTMLSpanElement);
const inViewResult = useInView(localRef, {
once: inViewOnce,
margin: inViewMargin,
});
const isInView = !inView || inViewResult;
const words = React.useMemo(() => text.split(" "), [text]);
return (
<span ref={localRef} data-slot="writing-text" {...props}>
{words.map((word, index) => (
<motion.span
key={index}
className="inline-block will-change-transform will-change-opacity"
style={{ marginRight: spacing }}
initial={{ opacity: 0, y: 10 }}
animate={isInView ? { opacity: 1, y: 0 } : undefined}
transition={{
...transition,
delay: index * (transition?.delay ?? 0),
}}
>
{word}{" "}
</motion.span>
))}
</span>
);
}
export { WritingText, type WritingTextProps };
Update the import paths to match your project setup.
Usage
import { WritingText } from "@/components/core/writing-text";
export default function WritingTextExample() {
return (
<WritingText
className="text-4xl"
text="Writing Text With Effect"
spacing={9}
/>
);
}
Props
| Prop | Type | Default |
|---|---|---|
className? | string | - |
duration? | number | 2 |
delay? | number | 0.5 |
inView? | boolean | false |
inViewMargin? | string | 0px |
inViewOnce? | boolean | true |
spacing? | number | string | 5 |
text | string | - |
transition? | Transition | { type: 'spring', bounce: 0, duration: 2, delay: 0.5 } |