---
title: Infinite Scroll
description: Load more content as the user scrolls to the end of a list.
---
import Source from './_generated/infinite-scroll.mdx';

Place a sentinel at the end of a list; as it nears the viewport it fires and you load the next batch. A pending guard suppresses double-fires while a batch loads, and if the sentinel is still on screen afterwards (a short list that did not fill the viewport) it loads again. Mark it exhausted to stop observing and reveal an optional end slot.

<DemoFrame component="infinite-scroll" height={480} />

## Installation

```bash
npx touchcn add infinite-scroll
```

## Usage

<CodeGroup>

```html Angular
<tcn-infinite-scroll #infinite="tcnInfiniteScroll" [disabled]="exhausted()" (loadMore)="onLoadMore(infinite)">
  <span end>You're all caught up</span>
</tcn-infinite-scroll>
```

```tsx React
import { TcnInfiniteScroll } from '@/components/ui/infinite-scroll';

<TcnInfiniteScroll onLoadMore={onLoadMore} disabled={exhausted} end={<span>You're all caught up</span>} />
```

```vue Vue
<script setup lang="ts">
import { TcnInfiniteScroll } from '@/components/ui/infinite-scroll';
</script>

<template>
  <TcnInfiniteScroll :on-load-more="onLoadMore" :disabled="exhausted">
    <template #end>
      <span>You're all caught up</span>
    </template>
  </TcnInfiniteScroll>
</template>
```

</CodeGroup>

On Angular, load the batch when `loadMore` fires and call `complete()` (via the template ref) to release the guard. On React, return a Promise from `onLoadMore` — the guard holds until it settles.

## Props

| Prop                      | Type                          | Default | Description                                             |
| ------------------------- | ----------------------------- | ------- | ------------------------------------------------------- |
| `loadMore` / `onLoadMore` | `() => void \| Promise<void>` | —       | Fires when the sentinel nears the viewport.             |
| `distance`                | `string`                      | `'15%'` | Bottom `rootMargin` — how early to fire.                |
| `disabled`                | `boolean`                     | `false` | Stops observing and reveals the end slot (exhausted).   |
| `end` / `[end]`           | slot                          | —       | Content shown once the list is exhausted.               |
| `complete()`              | method (Angular)              | —       | Releases the guard after a batch; React uses the Promise. |

<Source />
