Virtual List Widget
The virtual list widget efficiently renders large lists by only creating VNodes for items within the visible viewport plus an overscan buffer. This enables smooth rendering of datasets with 100,000+ items.Basic Usage
Item Height Modes
Fixed Height (Fastest)
When all items have the same height, use a fixed number:Variable Height (Pre-computed)
When item heights are known in advance:Estimated Height (Dynamic)
For items with unknown heights, provide an estimate. The list measures actual heights and corrects offsets:Keyboard Navigation
Built-in Navigation
Enabled by default:- Arrow Up/Down: Move selection
- Page Up/Down: Jump by viewport height
- Home/End: Jump to first/last item
Wrap Around
Disable Navigation
Selection Handling
Scroll Management
Controlled Scroll
Scroll Direction
Control mouse wheel behavior:Overscan Buffer
Control how many items to render outside the visible viewport:- Pro: Smoother scrolling (less pop-in)
- Con: More VNodes rendered
- Pro: Fewer VNodes (better for very complex items)
- Con: Slight pop-in during fast scrolling
Large Dataset Example (100K+ Items)
Custom Selection Style
Complex Item Rendering
Performance Characteristics
| Metric | Fixed Height | Variable Height | Estimated Height |
|---|---|---|---|
| Initial render | ~5ms | ~5ms | ~5ms |
| Scroll update | ~1ms | ~2ms | ~2ms |
| Offset calculation | O(1) | O(n) + binary search | O(n) + corrections |
| Memory usage | O(viewport + overscan) | O(viewport + overscan + offset array) | O(viewport + overscan + offset array + measurements) |
| Best for | Uniform items | Known heights | Dynamic content |
Comparison with Regular Rendering
Props Reference
VirtualListProps
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | Required | Widget identifier |
items | readonly T[] | Required | Data array to render |
itemHeight | number | (item: T, index: number) => number | — | Fixed or computed height |
estimateItemHeight | number | (item: T, index: number) => number | — | Height estimate for dynamic content |
measureItemHeight | (item: T, index: number, ctx: MeasureCtx) => number | — | Custom measurement function |
renderItem | (item: T, index: number, focused: boolean) => VNode | Required | Item render function |
overscan | number | 3 | Items to render outside viewport |
keyboardNavigation | boolean | true | Enable arrow key navigation |
wrapAround | boolean | false | Wrap selection end→start |
scrollDirection | "natural" | "traditional" | "traditional" | Mouse wheel direction |
selectionStyle | TextStyle | — | Focused item style |
onScroll | (scrollTop: number, visibleRange: [number, number]) => void | — | Scroll callback |
onSelect | (item: T, index: number) => void | — | Selection callback (Enter key) |
focusable | boolean | true | Include in tab order |
accessibleLabel | string | — | Accessibility label |
focusConfig | FocusConfig | — | Focus appearance |
Related Widgets
- Table - Virtualized table with columns
- Tree - Hierarchical virtualized lists
- Logs Console - High-volume log streaming
Location in Source
- Implementation:
packages/core/src/widgets/virtualList.ts - Types:
packages/core/src/widgets/types.ts:952-1008 - Factory:
packages/core/src/widgets/ui.ts:virtualList()