For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/en/llms-full.txt, and this page is available as Markdown at https://ifhover.github.io/leaf-ui/en/components/virtual-list.md.

VirtualList

Browse large lists smoothly.

Basic usage

basic.tsx
import { VirtualList } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function VirtualListBasic() {
  const [items] = useState(() =>
    Array.from({ length: 10000 }, (_, index) => ({
      id: String(index),
      name: `Item ${index + 1}`,
    })),
  );
  return (
    <VirtualList
      items={items}
      itemKey={(item) => item.id}
      height={240}
      estimateSize={44}
      renderItem={(item) => <div style={{ padding: '12px 16px' }}>{item.name}</div>}
    />
  );
}

More examples

advanced.tsx
import { Button, Space, VirtualList } from '@ifhover/leaf-ui';

import { useRef, useState } from 'react';

export function VirtualListDynamic() {
  const list = useRef<import('@ifhover/leaf-ui').VirtualListHandle>(null);
  const [items] = useState(() =>
    Array.from({ length: 1000 }, (_, index) => ({
      id: String(index),
      text: 'Content with varying length. '.repeat((index % 3) + 1),
    })),
  );
  return (
    <Space direction="vertical" align="stretch">
      <Button variant="outline" onClick={() => list.current?.scrollToIndex(500, 'start')}>
        Go to item 501
      </Button>
      <VirtualList
        ref={list}
        items={items}
        itemKey={(item) => item.id}
        height={220}
        estimateSize={60}
        renderItem={(item) => (
          <div style={{ padding: 16 }}>
            <strong>#{item.id}</strong>
            <p style={{ margin: '4px 0' }}>{item.text}</p>
          </div>
        )}
      />
    </Space>
  );
}

Usage

Keep itemKey stable. estimateSize is used initially; rows are measured afterward. SSR outputs a deterministic initial window that adjusts after mounting.

Types

Import these types for data, callbacks and refs.

import type { VirtualListHandle, VirtualListProps } from '@ifhover/leaf-ui';

VirtualListHandle API

PropertyTypeDefaultDescription
elementHTMLDivElement | nullRequiredScroll container element
scrollToIndex(index: number, align?: 'auto' | 'start' | 'center' | 'end') => voidRequiredScroll to an item
scrollToOffset(offset: number) => voidRequiredScroll to an offset

VirtualListProps API

PropertyTypeDefaultDescription
itemsreadonly T[]RequiredItems; keep keys unique and stable
itemKey(item: T, index: number) => KeyRequiredReturn a stable identifier
renderItem(item: T, index: number) => ReactNodeRequiredCustom item renderer
heightnumber320Height, numbers are in pixels
estimateSizenumber | ((item: T, index: number) => number)40Estimated item size; actual size is measured
overscannumber5Items rendered outside the visible range
emptyContentReactNode—Empty list content
horizontalbooleanfalseHorizontal virtual list