Prism Reveal Text
Text that materializes behind a traveling prism: the fill is a 300%-wide gradient — one third transparent, a five-stop prism band (violet, red, amber, lavender, blue) riding the reveal edge, then solid ink — clipped to the glyphs. Animating backgroundPosition sweeps the edge across so characters appear out of a flash of refracted color; both directions plus a custom-color dynamic variant.
TextReactMotionTailwind CSS
CSSTailwind
Manual
Create a file and paste the following code into it.
prism-reveal-text.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"use client";
import { useMemo, useRef } from "react";
import { motion, useInView } from "motion/react";
import { cn } from "@/lib/cn";
/* ------------------------------------------------------------------ */
/* PrismRevealText */
/* ------------------------------------------------------------------ */
type RevealVariant = "prism-rtl" | "prism-ltr" | "dynamic";
interface PrismRevealTextProps {
text: string;
/** Sweep duration in seconds [Optional, default: 0.9] */
duration?: number;
delay?: number;
repeat?: boolean;
repeatDelay?: number;
/** Stops for the dynamic variant's reveal edge [Optional] */
colors?: string[];
ease?: "linear" | "easeIn" | "easeOut" | "easeInOut";
/** Which edge the ink appears from [Optional, default: "prism-rtl"] */
variant?: RevealVariant;
className?: string;
startOnView?: boolean;
once?: boolean;
}
const INK = "light-dark(#0a0a0a, #f5f5f5)";
/* The house prism — coral, cream, mint, lavender, ultramarine (the kinetic
landing palette) — riding the reveal edge like light through a lens. */
const PRISM_RTL =
"#F4574D 40%, #FFE29E 45%, #BDEDC9 50%, #898FE9 55%, #202DED 60%";
const PRISM_LTR =
"#202DED 40%, #898FE9 45%, #BDEDC9 50%, #FFE29E 55%, #F4574D 60%";
/**
* Text that materializes behind a traveling prism: the fill is a 300%-wide
* gradient — one third transparent (not yet revealed), a five-stop prism
* band at the edge, then solid ink — clipped to the glyphs, and animating
* backgroundPosition sweeps the edge across so characters appear out of a
* flash of refracted color.
* @param {string} text - Text to reveal [Required]
* @param {RevealVariant} variant - Reveal direction or custom colors [Optional, default: "prism-rtl"]
*/
export function PrismRevealText({
text,
duration = 0.9,
delay = 0,
repeat = false,
repeatDelay = 0.5,
colors,
ease = "linear",
variant = "prism-rtl",
className,
startOnView = true,
once = true,
}: PrismRevealTextProps) {
const ref = useRef<HTMLSpanElement | null>(null);
const inView = useInView(ref, { once });
const backgroundImage = useMemo(() => {
if (variant === "prism-rtl") {
return `linear-gradient(90deg, transparent 0%, transparent 33.33%, ${PRISM_RTL}, ${INK} 66.67%, ${INK})`;
}
if (variant === "prism-ltr") {
return `linear-gradient(90deg, ${INK} 0%, ${INK} 33.33%, ${PRISM_LTR}, transparent 66.67%, transparent)`;
}
const stops = colors ?? ["rgb(96,165,250)", "rgb(191,219,254)"];
const span = Math.max(stops.length - 1, 1);
const band = stops
.map((c, i) => `${c} ${(33.33 + (i / span) * 33.34).toFixed(2)}%`)
.join(", ");
return `linear-gradient(90deg, ${INK} 0%, ${INK} 33.33%, ${band}, transparent 66.67%, transparent)`;
}, [variant, colors]);
const from = variant === "prism-rtl" ? "0% center" : "100% center";
const to = variant === "prism-rtl" ? "100% center" : "0% center";
return (
<motion.span
ref={ref}
className={cn("relative inline-block bg-clip-text pb-[0.15em] text-transparent", className)}
style={{ backgroundImage, backgroundSize: "300% 100%", backgroundRepeat: "no-repeat" }}
initial={{ backgroundPosition: from }}
animate={!startOnView || inView ? { backgroundPosition: to } : {}}
transition={{
backgroundPosition: {
duration,
delay,
ease,
repeat: repeat ? Infinity : 0,
repeatDelay,
},
}}
>
{text}
</motion.span>
);
}
Update the import paths to match your project setup.
Similar components
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryText
ReactMotionTailwind CSS
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryText
ReactMotionTailwind CSS