Text Loop
Text animation that transitions between multiple items, creating an engaging looping effect
Examples
Text Loop Basic
How can I assist you today?
Text Loop with custom variants and transition
Beautiful templates for
Founders
Text Loop with onIndexChange
You can use the onIndexChange
prop to trigger a callback function when the index changes. In this example, we use it to create alternating animation directions.
A Little Lost・Arthur Russell
Code
'use client';
import { cn } from '@/lib/utils';
import { motion, AnimatePresence, Transition, Variants } from 'motion/react';
import { useState, useEffect, Children } from 'react';
type TextLoopProps = {
children: React.ReactNode[];
className?: string;
interval?: number;
transition?: Transition;
variants?: Variants;
onIndexChange?: (index: number) => void;
};
export function TextLoop({
children,
className,
interval = 2,
transition = { duration: 0.3 },
variants,
onIndexChange,
}: TextLoopProps) {
const [currentIndex, setCurrentIndex] = useState(0);
const items = Children.toArray(children);
useEffect(() => {
const intervalMs = interval * 1000;
const timer = setInterval(() => {
setCurrentIndex((current) => {
const next = (current + 1) % items.length;
onIndexChange?.(next);
return next;
});
}, intervalMs);
return () => clearInterval(timer);
}, [items.length, interval, onIndexChange]);
const motionVariants: Variants = {
initial: { y: 20, opacity: 0 },
animate: { y: 0, opacity: 1 },
exit: { y: -20, opacity: 0 },
};
return (
<div className={cn('relative inline-block whitespace-nowrap', className)}>
<AnimatePresence mode='popLayout' initial={false}>
<motion.div
key={currentIndex}
initial='initial'
animate='animate'
exit='exit'
transition={transition}
variants={variants || motionVariants}
>
{items[currentIndex]}
</motion.div>
</AnimatePresence>
</div>
);
}
Component API
Text Loop
Prop | Type | Default | Description |
---|---|---|---|
children | React.ReactNode[] | The text content to be animated. | |
className | string | Additional CSS classes for styling. | |
interval | number | 2000 | Time interval between text changes in milliseconds. |
transition | Transition | Animation transition settings. Can't be more than inerval | |
variants | Variants | Custom animation variants. | |
onIndexChange | (index: number) => void | Callback function that triggers when the index changes. |