Infinite Scroll

DnD & Interaction

Automatic content loading on scroll.

Preview

Usage

example.jsx
import { InfiniteScroll } from "@/components/ui/infinite-scroll";

export default function Example() {
  return <InfiniteScroll />;
}

Source Code

Copy this file into components/ui/infinite-scroll.jsx in your project.

infinite-scroll.jsx
"use client";

import { forwardRef, useEffect, useRef, useCallback } from "react";
import { cn } from "@/lib/utils";

const InfiniteScroll = forwardRef(({ className, onLoadMore, hasMore, loading, children, threshold = 100, ...props }, ref) => {
  const sentinelRef = useRef(null);

  useEffect(() => {
    if (!hasMore || loading) return;
    const observer = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) onLoadMore?.(); },
      { rootMargin: `${threshold}px` }
    );
    const el = sentinelRef.current;
    if (el) observer.observe(el);
    return () => { if (el) observer.unobserve(el); };
  }, [hasMore, loading, onLoadMore, threshold]);

  return (
    <div ref={ref} className={cn(className)} {...props}>
      {children}
      <div ref={sentinelRef} className="h-1" />
      {loading && <div className="flex justify-center py-4"><div className="h-6 w-6 animate-spin rounded-full border-2 border-muted border-t-primary" /></div>}
    </div>
  );
});
InfiniteScroll.displayName = "InfiniteScroll";

export { InfiniteScroll };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge