Getting Started
Components
Search for a command to run...
import { BlockTextReveal } from "@/registry/tween/block-text-reveal"
const INK = "#0b0b0c"
const CREAM = "#f1ece1"
const WINE = "#b8121b"
const BONE = "#e8e2d3"
const NIGHT = "#111418"
const sectionBase =
"@container/block relative flex w-full flex-col overflow-hidden"
const minPreview = { minHeight: "var(--preview-h, 100vh)" }
export function BlockTextRevealDemo() {
return (
<div className="w-full" style={{ backgroundColor: CREAM, color: INK }}>
<section
className={`${sectionBase} items-center justify-center px-6 py-24 text-center`}
style={{ ...minPreview, backgroundColor: CREAM }}
>
<BlockTextReveal blockColor={INK}>
<p className="mb-8 text-[clamp(0.7rem,1.4cqi,0.95rem)] font-medium tracking-[0.35em] uppercase opacity-80">
Issue 01 — The Reveal Series
</p>
</BlockTextReveal>
<BlockTextReveal blockColor={WINE} stagger={0.1}>
<h1
className="w-[min(92%,18ch)] text-center text-[clamp(2.5rem,12cqi,9rem)] leading-[0.95] font-black [letter-spacing:-0.04em] uppercase"
style={{ color: WINE }}
>
Bold type, revealed
</h1>
</BlockTextReveal>
<BlockTextReveal blockColor={INK}>
<p className="mt-10 w-[min(80%,42ch)] text-center text-[clamp(0.9rem,1.6cqi,1.05rem)] font-medium tracking-[0.2em] uppercase opacity-70">
A block sweeps, the words land hard
</p>
</BlockTextReveal>
</section>
<section
className={`${sectionBase} items-start justify-center px-8 py-24 md:px-16`}
style={{ ...minPreview, backgroundColor: BONE }}
>
<div className="grid w-full grid-cols-1 gap-12 md:grid-cols-[1fr_3fr]">
<BlockTextReveal blockColor={WINE}>
<p
className="text-[clamp(1rem,1.8cqi,1.25rem)] font-semibold tracking-[0.25em] uppercase"
style={{ color: WINE }}
>
§ 02 / The Method
</p>
</BlockTextReveal>
<BlockTextReveal blockColor={INK} stagger={0.13}>
<p className="w-[min(100%,40ch)] text-left text-[clamp(1.5rem,4.2cqi,3rem)] leading-[1.15] font-medium [letter-spacing:-0.015em]">
A colored block slides across each line, then lifts to expose the
text beneath. Stagger it word by word for a headline that arrives
with weight.
</p>
</BlockTextReveal>
</div>
</section>
<section
className={`${sectionBase} items-center justify-center px-6 py-24 text-center`}
style={{ ...minPreview, backgroundColor: NIGHT, color: CREAM }}
>
<BlockTextReveal blockColor={WINE}>
<p
className="mb-10 text-[clamp(0.7rem,1.4cqi,0.95rem)] font-medium tracking-[0.4em] uppercase"
style={{ color: WINE }}
>
— The Tween Way
</p>
</BlockTextReveal>
<BlockTextReveal blockColor={CREAM} alternate stagger={0.14}>
<h2
className="w-[min(92%,22ch)] text-center text-[clamp(1.75rem,6.2cqi,4.5rem)] leading-[1.05] font-medium [letter-spacing:-0.025em]"
style={{ color: CREAM }}
>
Reverse the direction, alternate the blocks, and the same effect
feels brand new.
</h2>
</BlockTextReveal>
<div className="mt-12 flex items-center gap-4 opacity-70">
<span className="h-px w-12" style={{ backgroundColor: CREAM }} />
<BlockTextReveal blockColor={CREAM}>
<p
className="text-[clamp(0.7rem,1.3cqi,0.85rem)] font-medium tracking-[0.3em] uppercase"
style={{ color: CREAM }}
>
Reveal · Stagger 400 · Block
</p>
</BlockTextReveal>
<span className="h-px w-12" style={{ backgroundColor: CREAM }} />
</div>
</section>
<section
className={`${sectionBase} items-center justify-center px-6 py-24 text-center`}
style={{ ...minPreview, backgroundColor: CREAM }}
>
<BlockTextReveal blockColor={WINE} stagger={0.11}>
<h1
className="w-[min(92%,20ch)] text-center text-[clamp(2.25rem,11cqi,8rem)] leading-[0.92] font-black [letter-spacing:-0.045em] uppercase"
style={{ color: WINE }}
>
Make an
<br />
entrance worth it
</h1>
</BlockTextReveal>
<div className="mt-12 flex w-[min(90%,60ch)] flex-col items-center gap-2">
<BlockTextReveal blockColor={INK}>
<p className="text-[clamp(0.8rem,1.4cqi,0.95rem)] font-medium tracking-[0.3em] uppercase opacity-70">
Design · Motion · Ship
</p>
</BlockTextReveal>
<BlockTextReveal blockColor={INK}>
<p className="text-[clamp(0.75rem,1.2cqi,0.85rem)] font-medium tracking-[0.5em] uppercase opacity-50">
Tween
</p>
</BlockTextReveal>
</div>
</section>
</div>
)
}
import { BlockTextReveal } from "@/components/ui/block-text-reveal"<BlockTextReveal blockColor="#b8121b">
<h1>Motion is part of the message.</h1>
</BlockTextReveal>
<BlockTextReveal blockColor="#000" alternate>
<p>Every line is masked, wiped, and lifted into place.</p>
</BlockTextReveal>
<BlockTextReveal blockColor="#000" animateOnScroll={false}>
<p>Play the reveal immediately on mount.</p>
</BlockTextReveal>The child is split into lines, and each line gets its own block overlay. The block first wipes in to fully cover the line, then wipes back out to expose the text, which simultaneously lifts up by lineLift pixels. Lines fire in sequence with stagger, so the paragraph assembles top to bottom. Set alternate to flip every other line's wipe direction for a woven effect, or disable animateOnScroll to run the whole sequence as soon as the component mounts.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Single text element (or wrapper) to animate. |
animateOnScroll | boolean | true | Trigger the reveal on scroll-into-view. false plays immediately. |
delay | number | 0 | Delay (seconds) before the first line starts. |
blockColor | string | "#000" | CSS color for the wiping block. |
stagger | number | 0.07 | Per-line stagger (seconds). |
duration | number | 0.42 | Base tween budget (seconds). Cover, reveal, and lift durations derive from this. |
ease | string | "power4.in" | Easing for the wipe-in (cover phase). |
easeOut | string | "expo.out" | Easing for the wipe-out (reveal phase) and the line lift. |
lineLift | number | 10 | How far each line lifts (px) as it becomes visible. Set 0 to disable. |
alternate | boolean | false | If true, alternate lines wipe in from the right instead of the left. |
start | string | "top 90%" | ScrollTrigger start value when animateOnScroll is true. |
scroller | HTMLElement | string | null | — | Optional ScrollTrigger scroller; defaults to the ambient preview scroller. |
className | string | — | Merged onto the cloned child element. |