profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
reveal.tsx 1,230 bytes
1 'use client';
2
3 import { useEffect, useRef, useState } from 'react';
4 import { cn } from '@/lib/utils';
5
6 /** Reveals its children with a soft slide-up the first time they scroll into view. */
7 export function Reveal({
8 children,
9 className,
10 delay = 0,
11 }: {
12 children: React.ReactNode;
13 className?: string;
14 delay?: number;
15 }) {
16 const ref = useRef<HTMLDivElement>(null);
17 const [shown, setShown] = useState(false);
18
19 useEffect(() => {
20 if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
21 setShown(true);
22 return;
23 }
24 const el = ref.current;
25 if (!el) return;
26 const observer = new IntersectionObserver(
27 (entries) => {
28 if (entries[0]?.isIntersecting) {
29 setShown(true);
30 observer.disconnect();
31 }
32 },
33 { threshold: 0.15 },
34 );
35 observer.observe(el);
36 return () => observer.disconnect();
37 }, []);
38
39 return (
40 <div
41 ref={ref}
42 style={{ transitionDelay: `${delay}ms` }}
43 className={cn(
44 'transition-all duration-700 ease-out motion-reduce:transition-none',
45 shown ? 'translate-y-0 opacity-100' : 'translate-y-5 opacity-0',
46 className,
47 )}
48 >
49 {children}
50 </div>
51 );
52 }
53