Text Animatinon

A timeline animation using Framer Motion that animates items one by one as you reach each specific section

Installation

npm install motion @motionone/utils
framer-timeline.tsx
1
import { type HTMLMotionProps, motion, useInView } from "motion/react"
2
import type React from "react"
3
import type { Variants } from "motion/react"
4
5
type TimelineContentProps<T extends keyof HTMLElementTagNameMap> = {
6
children: React.ReactNode
7
animationNum: number
8
className?: string
9
timelineRef: React.RefObject<HTMLElement | null>
10
as?: T
11
customVariants?: Variants
12
once?: boolean
13
} & HTMLMotionProps<T>
14
15
export const TimelineContent = <T extends keyof HTMLElementTagNameMap = "div">({
16
children,
17
animationNum,
18
timelineRef,
19
className,
20
as,
21
customVariants,
22
once=false,
23
...props
24
}: TimelineContentProps<T>) => {
25
const defaultSequenceVariants = {
26
visible: (i: number) => ({
27
filter: "blur(0px)",
28
y: 0,
29
opacity: 1,
30
transition: {
31
delay: i * 0.5,
32
duration: 0.5,
33
},
34
}),
35
hidden: {
36
filter: "blur(20px)",
37
y: 0,
38
opacity: 0,
39
},
40
}
41
42
// Use custom variants if provided, otherwise use default
43
const sequenceVariants = customVariants || defaultSequenceVariants
44
45
const isInView = useInView(timelineRef, {
46
once
47
})
48
49
const MotionComponent = motion[as || "div"] as React.ElementType
50
51
return (
52
<MotionComponent
53
initial="hidden"
54
animate={isInView ? "visible" : "hidden"}
55
custom={animationNum}
56
variants={sequenceVariants}
57
className={className}
58
{...props}
59
>
60
{children}
61
</MotionComponent>
62
)
63
}

Props

PropTypeDefaultDescription
childrenReact.ReactNodeThe content to be displayed within the timeline.
askeyof HTMLElementTagNameMapdivThe HTML element to use for the timeline.
timelineRefReact.RefObject<HTMLDivElement>A reference to the timeline element for manipulation.
oncebooleanfalseWhether to animate only once.
variantsVariantsA set of variants to animate the timeline.