Text animations
Color Cycle Text
A self-contained component that animates a span of text by cycling through a given array of colors.
Installation
CLI
Installation via the CLI is coming soon. For now, please follow the manual installation instructions below.
Manual
- Install the following dependencies:
npm install gsap @gsap/react
yarn add gsap @gsap/react
pnpm add gsap @gsap/react
- Copy and paste the following code into your project.
'use client';
import React, { useRef, useState, useEffect } from 'react';
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
import { cn } from '@/lib/utils';
/**
* A curated list of common GSAP easing functions to provide autocompletion.
*/
type GsapEase =
| 'none'
| 'power1'
| 'power1.in'
| 'power1.out'
| 'power1.inOut'
| 'power2'
| 'power2.in'
| 'power2.out'
| 'power2.inOut'
| 'power3'
| 'power3.in'
| 'power3.out'
| 'power3.inOut'
| 'power4'
| 'power4.in'
| 'power4.out'
| 'power4.inOut'
| 'back'
| 'back.in'
| 'back.out'
| 'back.inOut'
| 'elastic'
| 'elastic.in'
| 'elastic.out'
| 'elastic.inOut'
| 'bounce'
| 'bounce.in'
| 'bounce.out'
| 'bounce.inOut'
| 'circ'
| 'circ.in'
| 'circ.out'
| 'circ.inOut'
| 'expo'
| 'expo.in'
| 'expo.out'
| 'expo.inOut'
| 'sine'
| 'sine.in'
| 'sine.out'
| 'sine.inOut';
interface ColorCycleTextProps extends React.HTMLAttributes<HTMLSpanElement> {
/** The text content to display and animate. */
text: string;
/** An array of CSS color strings to cycle through. Must contain at least two colors for the effect to run. */
colors: string[];
/** The duration of the color transition in seconds. */
duration?: number;
/**
* The GSAP easing function for the animation. Provides autocompletion for common eases
* but also accepts any custom GSAP ease string.
*/
ease?: GsapEase | (string & {});
}
/**
* A self-contained component that animates a span of text by cycling through a given array of colors.
* It manages its own animation state locally without external dependencies.
*/
const ColorCycleText = React.forwardRef<HTMLSpanElement, ColorCycleTextProps>(
(
{
text,
colors,
duration = 0.8,
ease = 'power1.inOut',
className,
...props
},
ref
) => {
const textRef = useRef<HTMLSpanElement>(null);
const [currentColorIndex, setCurrentColorIndex] = useState(0);
useEffect(() => {
setCurrentColorIndex(0);
}, [colors.length]);
useGSAP(
() => {
if (!textRef.current || colors.length < 2) {
if (textRef.current) {
gsap.set(textRef.current, { color: colors || 'inherit' });
}
return;
}
gsap.to(textRef.current, {
color: colors[currentColorIndex],
duration,
ease,
onComplete: () => {
setCurrentColorIndex(
(prevIndex) => (prevIndex + 1) % colors.length
);
},
});
},
{
scope: textRef,
dependencies: [currentColorIndex, colors, duration, ease],
}
);
return (
<span
ref={textRef}
className={cn('inline-block', className)}
style={{ color: colors || 'inherit', ...props.style }}
{...props}
>
{text}
</span>
);
}
);
ColorCycleText.displayName = 'ColorCycleText';
export { ColorCycleText };
Usage
Import the component and provide it with text
and an array of colors
.
import { ColorCycleText } from '@/components/ui/color-cycle-text';
export default function MyComponent() {
const brandColors = ['#6366F1', '#EC4899', '#F59E0B'];
const statusColors = ['#22C55E', '#FBBF24', '#EF4444'];
return (
<h1 className='text-4xl font-bold'>
Build
<ColorCycleText
text=' beautiful '
colors={brandColors}
className='text-5xl'
/>
and
<ColorCycleText
text=' dynamic '
colors={statusColors}
duration={2}
ease='bounce.out'
className='text-5xl'
/>
interfaces.
</h1>
);
}
Props
This component accepts all standard <span>
attributes like className
and style
.
Prop | Type | Default | Description |
---|---|---|---|
text | string | (required) | The text content to display and animate. |
colors | string[] | (required) | An array of CSS color strings to cycle through. |
duration | number | 0.8 | The duration of the color transition in seconds. |
ease | GsapEase | (string & {}) | 'power1.inOut' | The GSAP easing function for the animation. Provides autocompletion and accepts custom ease strings. |