Virtualizer
Preview: 10k rows
Wrap a ListBox, GridList, Tree or Table to render only the visible rows. The collection inside needs a fixed height and overflow:auto.
Import
import { VirtualList } from '@marbleui/ui'Props
<VirtualList>
| Prop | Type | Default | Description |
|---|---|---|---|
| children *required | ReactNode | — | |
| estimatedRowHeight | number | — | |
| gap | number | 0 | |
| padding | number | 4 | |
| rowHeight | number | — | Fixed row height in px (fast path). Omit with `estimatedRowHeight` for variable rows. |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria ListLayout · React Aria Virtualizer. Follow the primitive's docs for the full keyboard map.
Usage notes
Renders only the visible rows of a long list. Exported as VirtualList; wrap a ListBox, ListView, Tree or Table when it holds thousands of items.
<VirtualList rowHeight={36}>
<ListBox aria-label="People" items={rows} className="h-72 overflow-auto">
{(r) => <ListBoxItem id={r.id}>{r.name}</ListBoxItem>}
</ListBox>
</VirtualList>
- The wrapped collection needs a fixed height and
overflow-auto, or nothing scrolls. - Use a fixed
rowHeightfor the fast path; for variable rows omit it and passestimatedRowHeight.gapandpadding(default 4) are in px. - Pass data through
itemswith a render function, as in the example, rather than hand-written children.
Example source · show· hide
import { useMemo } from 'react'
import { ListBox, ListBoxItem } from '../listbox'
import { VirtualList } from './virtualizer'
const first = ['Ada', 'Grace', 'Alan', 'Maya', 'Charles', 'Katherine', 'Linus', 'Margaret', 'Tim', 'Barbara']
const last = ['Lovelace', 'Hopper', 'Turing', 'Chen', 'Webb', 'Johnson', 'Torvalds', 'Hamilton', 'Berners-Lee', 'Liskov']
function TenThousand() {
const rows = useMemo(() => Array.from({ length: 10_000 }, (_, i) => ({ id: i, name: `${first[i % 10]} ${last[(i * 7) % 10]}`, n: i + 1 })), [])
return (
<div className="flex flex-col gap-2">
<VirtualList rowHeight={36}>
<ListBox aria-label="10,000 people" selectionMode="multiple" items={rows} className="h-72 w-72 overflow-auto">
{(r) => <ListBoxItem id={r.id} textValue={r.name}>#{r.n} · {r.name}</ListBoxItem>}
</ListBox>
</VirtualList>
<span className="text-xs text-fg-subtle">10,000 rows, only ~10 in the DOM.</span>
</div>
)
}
export const styles = { '10k rows': TenThousand }Source: packages/ui/src/virtualizer/virtualizer.tsx
Catalog
- Category
- collections
- Priority
- Core
- Primitive
- react-aria
- React Aria
- Virtualizer