Shimmer Text
A light sweep across text for loading and AI 'thinking' states.
Thinking through your request…
Generating layoutcomponents/ui/shimmer-text.tsx
"use client";
import { motion } from "motion/react";
import { Loader2 } from "lucide-react";
import type { ReactNode } from "react";
/** A light sweep across text — ideal for "thinking…" or loading states. */
export function ShimmerText({ children, className = "", duration = 2 }: { children: ReactNode; className?: string; duration?: number }) {
return (
<motion.span
className={`bg-clip-text text-transparent ${className}`}
style={{ backgroundImage: "linear-gradient(90deg, #a1a1aa 0%, #a1a1aa 40%, #18181b 50%, #a1a1aa 60%, #a1a1aa 100%)", backgroundSize: "250% 100%" }}
animate={{ backgroundPosition: ["100% 0%", "-50% 0%"] }}
transition={{ duration, repeat: Infinity, ease: "linear" }}
>
{children}
</motion.span>
);
}
export default function Demo() {
return (
<div className="flex flex-col items-center gap-4">
<p className="flex items-center gap-2 text-lg font-medium">
<Loader2 className="size-4 animate-spin text-zinc-400" />
<ShimmerText>Thinking through your request…</ShimmerText>
</p>
<ShimmerText className="text-4xl font-semibold tracking-tight">Generating layout</ShimmerText>
</div>
);
}
Installation
Install the dependencies
$ npm i motion lucide-reactCopy the source into
components/ui/shimmer-text.tsxcomponents/ui/shimmer-text.tsx"use client"; import { motion } from "motion/react"; import { Loader2 } from "lucide-react"; import type { ReactNode } from "react"; /** A light sweep across text — ideal for "thinking…" or loading states. */ export function ShimmerText({ children, className = "", duration = 2 }: { children: ReactNode; className?: string; duration?: number }) { return ( <motion.span className={`bg-clip-text text-transparent ${className}`} style={{ backgroundImage: "linear-gradient(90deg, #a1a1aa 0%, #a1a1aa 40%, #18181b 50%, #a1a1aa 60%, #a1a1aa 100%)", backgroundSize: "250% 100%" }} animate={{ backgroundPosition: ["100% 0%", "-50% 0%"] }} transition={{ duration, repeat: Infinity, ease: "linear" }} > {children} </motion.span> ); } export default function Demo() { return ( <div className="flex flex-col items-center gap-4"> <p className="flex items-center gap-2 text-lg font-medium"> <Loader2 className="size-4 animate-spin text-zinc-400" /> <ShimmerText>Thinking through your request…</ShimmerText> </p> <ShimmerText className="text-4xl font-semibold tracking-tight">Generating layout</ShimmerText> </div> ); }Use it
The file exports the component and a
Demoshowing typical usage. Import whichever you need.