Introducing Nuvyx UI v1.0.0

Animated Text

A versatile text animation component that offers multiple animation types.

Cascade

Flicker

Blink

Blink

Expand

Expand

Rise

Rise

Glide

Glide

Elastic

Elastic

Float

Float

Installation Guide

1

Install Dependencies

Framer Motion

npm install framer-motion
2

Copy Component Code

Animated Text.tsx
TypeScript
1"use client";
2
3import { FC, useRef, useEffect } from "react";
4import {
5  HTMLMotionProps,
6  motion,
7  useAnimation,
8  useInView,
9} from "framer-motion";
10
11type AnimationType =
12  | "blink"
13  | "rise"
14  | "expand"
15  | "glide"
16  | "cascade"
17  | "flicker"
18  | "elastic"
19  | "float";
20
21interface Props extends HTMLMotionProps<"div"> {
22  text: string;
23  type?: AnimationType;
24  delay?: number;
25  duration?: number;
26  custom?: number;
27}
28
29const animationVariants = {
30  blink: {
31    container: {
32      hidden: { opacity: 0 },
33      visible: (i: number = 1) => ({
34        opacity: 1,
35        transition: { staggerChildren: 0.05, delayChildren: i * 0.3 },
36      }),
37    },
38    child: {
39      visible: {
40        opacity: 1,
41        y: 0,
42        transition: {
43          type: "spring",
44          damping: 12,
45          stiffness: 100,
46          y: {
47            type: "keyframes",
48            times: [0, 0.5, 1],
49            values: [0, -10, 0],
50          },
51        },
52      },
53      hidden: { opacity: 0, y: 10 },
54    },
55  },
56  rise: {
57    container: {
58      hidden: { opacity: 0 },
59      visible: {
60        opacity: 1,
61        transition: { staggerChildren: 0.1, delayChildren: 0.2 },
62      },
63    },
64    child: {
65      visible: { opacity: 1, y: 0, transition: { duration: 0.5 } },
66      hidden: { opacity: 0, y: 20 },
67    },
68  },
69  expand: {
70    container: {
71      hidden: { opacity: 0, scale: 0.8 },
72      visible: {
73        opacity: 1,
74        scale: 1,
75        transition: { staggerChildren: 0.05, delayChildren: 0.2 },
76      },
77    },
78    child: {
79      visible: {
80        opacity: 1,
81        scale: 1,
82        transition: {
83          type: "spring",
84          damping: 15,
85          stiffness: 400,
86          scale: {
87            type: "keyframes",
88            times: [0, 0.6, 1],
89            values: [0, 1.1, 1],
90          },
91        },
92      },
93      hidden: { opacity: 0, scale: 0 },
94    },
95  },
96  float: {
97    container: {
98      hidden: {},
99      visible: (i: number = 1) => ({
100        transition: { staggerChildren: 0.03, delayChildren: 0.2 * i },
101      }),
102    },
103    child: {
104      hidden: {
105        y: 50,
106        opacity: 0,
107      },
108      visible: {
109        y: 0,
110        opacity: 1,
111        transition: {
112          duration: 0.5,
113          ease: "easeOut",
114        },
115      },
116    },
117  },
118  glide: {
119    container: {
120      hidden: {},
121      visible: (i: number = 1) => ({
122        transition: { staggerChildren: 0.03, delayChildren: 0.2 * i },
123      }),
124    },
125    child: {
126      hidden: {
127        y: 20,
128        opacity: 0,
129      },
130      visible: {
131        y: 0,
132        opacity: 1,
133        transition: {
134          duration: 0.5,
135          ease: [0.22, 1, 0.36, 1],
136        },
137      },
138    },
139  },
140  elastic: {
141    container: {
142      hidden: {},
143      visible: (i: number = 1) => ({
144        transition: { staggerChildren: 0.03, delayChildren: 0.2 * i },
145      }),
146    },
147    child: {
148      hidden: {
149        y: 50,
150        opacity: 0,
151      },
152      visible: {
153        y: 0,
154        opacity: 1,
155        transition: {
156          type: "spring",
157          stiffness: 400,
158          damping: 10,
159        },
160      },
161    },
162  },
163  cascade: {
164    container: {
165      hidden: {},
166      visible: {},
167    },
168    child: {
169      hidden: {
170        opacity: 0,
171        y: `0.25em`,
172      },
173      visible: {
174        opacity: 1,
175        y: `0em`,
176        transition: {
177          duration: 0.65,
178          ease: [0.65, 0, 0.75, 1],
179        },
180      },
181    },
182  },
183  flicker: {
184    container: {
185      hidden: {},
186      visible: {},
187    },
188    child: {
189      hidden: {
190        opacity: 0,
191        y: `0.35em`,
192      },
193      visible: {
194        opacity: 1,
195        y: `0em`,
196        transition: {
197          duration: 0.45,
198          ease: [0.85, 0.1, 0.9, 1.2],
199        },
200      },
201    },
202  },
203};
204
205export const AnimateText: FC<Props> = ({
206  text,
207  type = "elastic",
208  custom = 1,
209  className = "",
210  ...props
211}: Props) => {
212  const ref = useRef(null);
213  const isInView = useInView(ref, { once: false });
214  const ctrls = useAnimation();
215
216  useEffect(() => {
217    if (isInView) {
218      ctrls.start("visible");
219    } else {
220      ctrls.start("hidden");
221    }
222  }, [isInView, ctrls]);
223
224  const letters = Array.from(text);
225  const { container, child } = animationVariants[type];
226
227  if (type === "cascade" || type === "flicker") {
228    return (
229      <h2
230        ref={ref}
231        className={`mt-6 text-3xl font-bold text-black dark:text-neutral-100 py-4 px-4 md:text-4xl ${className}`}
232      >
233        {text.split(" ").map((word, index) => {
234          return (
235            <motion.span
236              className="inline-block mr-[0.25em] whitespace-nowrap"
237              aria-hidden="true"
238              key={index}
239              initial="hidden"
240              animate={isInView ? "visible" : "hidden"}
241              variants={container}
242              transition={{
243                delayChildren: index * 0.13,
244                staggerChildren: 0.025,
245              }}
246            >
247              {word.split("").map((character, index) => {
248                return (
249                  <motion.span
250                    aria-hidden="true"
251                    key={index}
252                    variants={child}
253                    className="inline-block -mr-[0.01em]"
254                  >
255                    {character}
256                  </motion.span>
257                );
258              })}
259            </motion.span>
260          );
261        })}
262      </h2>
263    );
264  }
265
266  return (
267    <motion.h2
268      ref={ref}
269      style={{ display: "flex", overflow: "hidden" }}
270      role="heading"
271      variants={container}
272      initial="hidden"
273      animate={ctrls}
274      custom={custom}
275      className={`mt-6 text-3xl font-bold text-black dark:text-neutral-100 py-4 px-4 md:text-4xl ${className}`}
276      {...props}
277    >
278      {letters.map((letter, index) => (
279        <motion.span key={index} variants={child}>
280          {letter === " " ? "\u00A0" : letter}
281        </motion.span>
282      ))}
283    </motion.h2>
284  );
285};
286
3

Final Steps

Update Import Paths

Make sure to update the import paths in the component code to match your project structure. For example, change @/components/ui/button to match your UI components location.

Props

NameTypeDefaultDescription
textstring""The text content to be animated.
type"cascade" | "flicker" | "blink" | "expand" | "rise" | "glide" | "elastic" | "float""cascade"Animation style to apply to the text.
classNamestring""Additional CSS classes to apply to the component.
delaynumber0Delay before animation starts in milliseconds.
durationnumber0.5Duration of the animation in seconds.
staggerChildrennumber0.05Time between each character's animation for cascade effects.
oncebooleantrueIf true, animation plays only once when in view.
fontSizestring"2xl"Font size using Tailwind CSS size classes.
fontWeightstring"bold"Font weight using Tailwind CSS weight classes.
colorstring""Text color (uses theme colors if not specified).

Examples

Modern UI Library

Build beautiful interfaces with ease

Responsive Design

Ensure your UI looks great on all devices

Build fast and beautiful

Let's make web beautiful

Start building beautiful interfaces faster than ever before