Unified UI

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.

1
Item 1
row
2
Item 2
row
3
Item 3
row
4
Item 4
row
5
Item 5
row
6
Item 6
row
7
Item 7
row
8
Item 8
row
9
Item 9
row
10
Item 10
row

Installation

Install the component via the CLI in one command.

npx @work-rjkashyap/unified-ui add infinite-scroll
pnpm dlx @work-rjkashyap/unified-ui add infinite-scroll
npx @work-rjkashyap/unified-ui add infinite-scroll
bunx @work-rjkashyap/unified-ui add infinite-scroll

If 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-ui
pnpm add @work-rjkashyap/unified-ui
yarn add @work-rjkashyap/unified-ui
bun add @work-rjkashyap/unified-ui

Anatomy

import { InfiniteScroll } from "@work-rjkashyap/unified-ui";

Examples

Basic List

1
Item 1
row
2
Item 2
row
3
Item 3
row
4
Item 4
row
5
Item 5
row
6
Item 6
row
7
Item 7
row
8
Item 8
row
9
Item 9
row
10
Item 10
row

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

Record 1
Record 2
Record 3
Record 4
Record 5
Record 6
Record 7
Record 8

Loading State

1
Item 1
2
Item 2
3
Item 3
4
Item 4
5
Item 5
Loading more...

End of List

1
Item 1
2
Item 2
3
Item 3
4
Item 4
5
Item 5

🎉 You've seen everything!

With React Query

1
Item 1
row
2
Item 2
row
3
Item 3
row
4
Item 4
row
5
Item 5
row
6
Item 6
row
7
Item 7
row
8
Item 8
row
9
Item 9
row
10
Item 10
row

How It Works

  1. A hidden sentinel element is placed at the bottom of the children.
  2. An IntersectionObserver watches the sentinel with a configurable rootMargin (the threshold prop).
  3. When the sentinel enters the viewport, onLoadMore is called.
  4. While loading is true, the observer pauses to prevent duplicate calls.
  5. When hasMore is false, the sentinel is removed and the endMessage is shown.

Props

PropTypeDefaultDescription
childrenReactNodeContent to render (the list items).
loadingbooleanfalseWhether more data is being loaded.
hasMorebooleantrueWhether there is more data to load.
onLoadMore() => voidCallback to trigger loading more data.
thresholdstring"200px"Root margin for IntersectionObserver.
loadingIndicatorReactNodeCustom loading indicator.
endMessageReactNodeContent when all data has been loaded.
classNamestringAdditional CSS classes on the container.
sentinelClassNamestringAdditional 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

TokenUsage
--foregroundList item text
--muted-foregroundLoading text, end message
--borderDefault loading spinner ring
--primaryLoading spinner accent

On this page