Infinite Scroll
Scroll-triggered infinite loading with Intersection Observer, loading indicator, and end-of-list detection.
Basic
Scroll-triggered infinite loading with Intersection Observer, loading indicator, and end-of-list detection. Scroll down inside the container below to load more items.
Installation
Install the component via the CLI in one command.
npx @work-rjkashyap/unified-ui add infinite-scrollpnpm dlx @work-rjkashyap/unified-ui add infinite-scrollnpx @work-rjkashyap/unified-ui add infinite-scrollbunx @work-rjkashyap/unified-ui add infinite-scrollIf you haven't initialized your project yet, run npx @work-rjkashyap/unified-ui init first. See the CLI docs for details.
Or install the full package
Use this approach if you prefer to install the entire design system as a dependency instead of copying individual components.
npm install @work-rjkashyap/unified-uipnpm add @work-rjkashyap/unified-uiyarn add @work-rjkashyap/unified-uibun add @work-rjkashyap/unified-uiAnatomy
import { InfiniteScroll } from "@work-rjkashyap/unified-ui";Examples
Basic List
Card Grid
Card 1
Description for card 1. This is some placeholder content.
Card 2
Description for card 2. This is some placeholder content.
Card 3
Description for card 3. This is some placeholder content.
Card 4
Description for card 4. This is some placeholder content.
Card 5
Description for card 5. This is some placeholder content.
Card 6
Description for card 6. This is some placeholder content.
Custom Loading Indicator
Loading State
End of List
🎉 You've seen everything!
With React Query
How It Works
- A hidden sentinel element is placed at the bottom of the children.
- An
IntersectionObserverwatches the sentinel with a configurablerootMargin(thethresholdprop). - When the sentinel enters the viewport,
onLoadMoreis called. - While
loadingis true, the observer pauses to prevent duplicate calls. - When
hasMoreis false, the sentinel is removed and theendMessageis shown.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Content to render (the list items). |
loading | boolean | false | Whether more data is being loaded. |
hasMore | boolean | true | Whether there is more data to load. |
onLoadMore | () => void | — | Callback to trigger loading more data. |
threshold | string | "200px" | Root margin for IntersectionObserver. |
loadingIndicator | ReactNode | — | Custom loading indicator. |
endMessage | ReactNode | — | Content when all data has been loaded. |
className | string | — | Additional CSS classes on the container. |
sentinelClassName | string | — | Additional CSS classes on the sentinel element. |
Accessibility
- Container uses
aria-busy="true"when loading to announce state to screen readers. - The sentinel element is
aria-hidden— invisible to assistive technologies. - Works with keyboard scrolling and assistive technologies.
- Loading indicator provides visual and programmatic feedback.
For very large datasets where you need virtualization, combine
InfiniteScroll with VirtualList for optimal performance — InfiniteScroll
handles data fetching while VirtualList handles efficient rendering.
Design Tokens
| Token | Usage |
|---|---|
--foreground | List item text |
--muted-foreground | Loading text, end message |
--border | Default loading spinner ring |
--primary | Loading spinner accent |