diff --git a/src/components/messageStream/MessageStream.tsx b/src/components/messageStream/MessageStream.tsx index 42091bc..e8f60b9 100644 --- a/src/components/messageStream/MessageStream.tsx +++ b/src/components/messageStream/MessageStream.tsx @@ -62,7 +62,9 @@ export function MessageStream({ scope }: MessageStreamProps) { } } }, - { rootMargin: "200px" }, + // Prefetch the next page well before the sentinel is visible so content + // is already in place as the user scrolls — no blank gap at the bottom. + { rootMargin: "1000px" }, ); io.observe(el); return () => io.disconnect(); diff --git a/src/motion/Reveal.tsx b/src/motion/Reveal.tsx index 8c367c0..f527361 100644 --- a/src/motion/Reveal.tsx +++ b/src/motion/Reveal.tsx @@ -11,6 +11,13 @@ type RevealProps = { once?: boolean; /** Fraction of the element that must be visible to trigger (0-1). */ amount?: number; + /** + * Root margin for the in-view trigger (same semantics as IntersectionObserver + * `rootMargin`). The default positive bottom value reveals each block ~300px + * *before* it scrolls into view, so long feeds never show a blank gap that + * reads as "the bottom" before content fades in. + */ + margin?: string; }; /** @@ -24,6 +31,7 @@ export function Reveal({ className, once = true, amount = 0.15, + margin = "0px 0px 300px 0px", }: RevealProps) { return ( {children}