An open API service indexing awesome lists of open source software.

https://github.com/humanspeak/svelte-virtual-list

πŸ“œ A performant virtual list/scrolling component for Svelte applications - efficiently render large scrollable lists with minimal memory usage
https://github.com/humanspeak/svelte-virtual-list

infinite-scroll javascript performance svelte sveltekit typescript ui-components virtual-list virtual-scroll web-components

Last synced: 17 days ago
JSON representation

πŸ“œ A performant virtual list/scrolling component for Svelte applications - efficiently render large scrollable lists with minimal memory usage

Awesome Lists containing this project

README

          

# @humanspeak/svelte-virtual-list

[![NPM version](https://img.shields.io/npm/v/@humanspeak/svelte-virtual-list.svg)](https://www.npmjs.com/package/@humanspeak/svelte-virtual-list)
[![Build Status](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/npm-publish.yml)
[![Coverage Status](https://coveralls.io/repos/github/humanspeak/svelte-virtual-list/badge.svg?branch=main)](https://coveralls.io/github/humanspeak/svelte-virtual-list?branch=main)
[![License](https://img.shields.io/npm/l/@humanspeak/svelte-virtual-list.svg)](https://github.com/humanspeak/svelte-virtual-list/blob/main/LICENSE)
[![Downloads](https://img.shields.io/npm/dm/@humanspeak/svelte-virtual-list.svg)](https://www.npmjs.com/package/@humanspeak/svelte-virtual-list)
[![CodeQL](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/codeql.yml/badge.svg)](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/codeql.yml)
[![Install size](https://packagephobia.com/badge?p=@humanspeak/svelte-virtual-list)](https://packagephobia.com/result?p=@humanspeak/svelte-virtual-list)
[![Code Style: Trunk](https://img.shields.io/badge/code%20style-trunk-blue.svg)](https://trunk.io)
[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
[![Types](https://img.shields.io/npm/types/@humanspeak/svelte-virtual-list.svg)](https://www.npmjs.com/package/@humanspeak/svelte-virtual-list)
[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/humanspeak/svelte-virtual-list/graphs/commit-activity)

A high-performance virtual list component for Svelte 5 applications that efficiently renders large datasets with minimal memory usage.

## Features

- πŸ“ Dynamic item height handling - no fixed height required
- πŸ”„ Automatic resize handling for dynamic content
- πŸ“ TypeScript support with full type safety
- πŸš€ SSR compatible with hydration support
- ✨ Svelte 5 runes and snippets support
- 🎨 Customizable styling with class props
- πŸ› Debug mode for development
- 🎯 Smooth scrolling with configurable buffer zones
- 🧠 Memory-optimized for 10k+ items
- πŸ§ͺ Comprehensive test coverage (vitest and playwright)
- πŸš€ Progressive initialization for large datasets
- πŸ•ΉοΈ Programmatic scrolling with `scroll`
- ♾️ Infinite scroll support with `onLoadMore`

## Requirements

- Svelte 5
- Node.js 18+

## Installation

```bash
# Using pnpm (recommended)
pnpm add @humanspeak/svelte-virtual-list

# Using npm
npm install @humanspeak/svelte-virtual-list

# Using yarn
yarn add @humanspeak/svelte-virtual-list
```

## Basic Usage

```svelte

import SvelteVirtualList from '@humanspeak/svelte-virtual-list'

const items = Array.from({ length: 1000 }, (_, i) => ({
id: i,
text: `Item ${i}`
}))

{#snippet renderItem(item)}

{item.text}

{/snippet}

```

## Props

| Prop | Type | Default | Description |
| ---------------------------- | ----------------------------- | -------- | ----------------------------------------------------------------------------- |
| `items` | `T[]` | Required | Array of items to render |
| `defaultEstimatedItemHeight` | `number` | `40` | Initial height estimate used until items are measured |
| `bufferSize` | `number` | `20` | Number of items rendered outside the viewport |
| `debug` | `boolean` | `false` | Enable debug logging and visualizations |
| `containerClass` | `string` | `''` | Class for outer container |
| `viewportClass` | `string` | `''` | Class for scrollable viewport |
| `contentClass` | `string` | `''` | Class for content wrapper |
| `itemsClass` | `string` | `''` | Class for items container |
| `testId` | `string` | `''` | Base test id used in internal test hooks (useful for E2E/tests and debugging) |
| `onLoadMore` | `() => void \| Promise` | - | Callback when more data is needed for infinite scroll |
| `loadMoreThreshold` | `number` | `20` | Items from end to trigger `onLoadMore` |
| `hasMore` | `boolean` | `true` | Set to `false` when all data has been loaded |

## Programmatic Scrolling

Scroll to any item in the list using the `scroll` method. Useful for jump-to-item navigation, search results, and more.

```svelte

import SvelteVirtualList from '@humanspeak/svelte-virtual-list'
let listRef
const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Item ${i}` }))

function goToItem5000() {
listRef.scroll({ index: 5000, smoothScroll: true, align: 'auto' })
}

Scroll to item 5000

{#snippet renderItem(item)}

{item.text}

{/snippet}

```

### scroll() Options

| Option | Type | Default | Description |
| --------------------- | ------------------------------------------ | -------- | --------------------------------------- |
| `index` | `number` | Required | The item index to scroll to (0-based) |
| `smoothScroll` | `boolean` | `true` | Use smooth scrolling animation |
| `shouldThrowOnBounds` | `boolean` | `true` | Throw if index is out of bounds |
| `align` | `'auto' \| 'top' \| 'bottom' \| 'nearest'` | `'auto'` | Where to align the item in the viewport |

Alignment options:

- `'auto'` - Only scroll if not visible, align to nearest edge
- `'top'` - Always align to the top
- `'bottom'` - Always align to the bottom
- `'nearest'` - Scroll as little as possible to bring the item into view

## Infinite Scroll

Load more data automatically as users scroll near the end of the list. Perfect for paginated APIs, infinite feeds, and activity logs.

```svelte

import SvelteVirtualList from '@humanspeak/svelte-virtual-list'

let items = $state([...initialItems])
let hasMore = $state(true)

async function loadMore() {
const newItems = await fetchMoreItems()
items = [...items, ...newItems]
if (newItems.length === 0) {
hasMore = false
}
}

{#snippet renderItem(item)}

{item.text}

{/snippet}

```

### Infinite Scroll Behavior

- Triggers when scrolling near the end of the list
- Automatically triggers on mount if initial items are below threshold
- Prevents concurrent `onLoadMore` calls while loading
- Works with both sync and async callbacks

### Integration Guides

- [Infinite Scroll with Convex](documentation/CONVEX_INFINITE_SCROLL.md) - Real-time data + pagination with Convex backend

## Performance Considerations

- The `bufferSize` prop affects memory usage and scroll smoothness
- Items are measured and cached for optimal performance
- Dynamic height calculations happen automatically
- Resize observers handle container/content changes
- Virtual DOM updates are batched for efficiency

## Testing

### Unit Tests (Vitest)

```bash
# Run unit tests with coverage
pnpm test

# Run specific test files
pnpm vitest src/lib/utils/throttle.test.ts
```

### E2E Tests (Playwright)

```bash
# Install Playwright browsers (one-time setup)
npx playwright install

# Run all e2e tests
pnpm run test:e2e

# Run specific e2e test
npx playwright test tests/docs-visit.spec.ts --project=chromium

# Debug mode
npx playwright test --debug
```

## Project Structure

This is a **PNPM workspace** with two packages:

1. **`./`** - Main Svelte Virtual List component package
2. **`./docs`** - Documentation site with live demos and examples

### Development Commands

```bash
# Install dependencies for both packages
pnpm install

# Start development server
pnpm dev

# Start both package and docs
pnpm run dev:all

# Build package
pnpm run build

# Check TypeScript/Svelte
pnpm run check

# Format and lint code (uses Trunk)
trunk fmt
trunk check

# Run all tests
pnpm test:all
```

This project uses [Trunk](https://trunk.io) for formatting and linting. Trunk manages tool versions and runs checks automatically via pre-commit hooks.

## License

MIT Β© [Humanspeak, Inc.](LICENSE)

## Credits

Made with ❀️ by [Humanspeak](https://humanspeak.com)