← All primitives
Reveal
MotionFades + lifts children into view on scroll via IntersectionObserver. Dependency-free, respects reduced-motion.
Requires the .reveal / .reveal.in transition rules from globals.css — copy them into your global stylesheet, or children render but never animate in.
$
View raw manifest →npx shadcn@latest add https://prism.icglabs.co/r/reveal.jsoncomponents/prism/Reveal.tsx
"use client";
import { useEffect, useRef } from "react";
/**
* Reveal — fades + lifts its children into view on scroll via IntersectionObserver.
* Robust and dependency-free (no scroll-sync edge cases). The `.reveal/.in`
* styling lives in globals.css and respects prefers-reduced-motion.
*/
export function Reveal({
children,
className = "",
delay = 0,
}: {
children: React.ReactNode;
className?: string;
delay?: number;
}) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const io = new IntersectionObserver(
(entries) => {
for (const e of entries) {
if (e.isIntersecting) {
el.classList.add("in");
io.unobserve(el);
}
}
},
{ threshold: 0.15, rootMargin: "0px 0px -8% 0px" }
);
io.observe(el);
return () => io.disconnect();
}, []);
return (
<div ref={ref} className={`reveal ${className}`} style={{ transitionDelay: `${delay}s` }}>
{children}
</div>
);
}