API and Development
VirtualizedList from @prepared911/ui/virtualized-list maps items through renderItem. It keeps every row mounted and skips layout and paint outside the viewport with content-visibility: auto. estimatedItemSize reserves a block size for a row the browser has not laid out. getItemKey stabilizes identity. ref exposes scrollToIndex and scrollToOffset. onEndReached pages the list. emptyContent replaces the list when there are no rows.
Import:
| Prop | Type | Notes |
|---|---|---|
items | readonly T[] | The full array. Required. |
renderItem | (item: T, index: number) => ReactNode | Row content. By default the component owns the li. Required. |
rowElement | VirtualizedListRowElement | Element that wraps each row. ListItem (default) is an li. Presentation is a div role="presentation", for rows that already render their own li. |
estimatedItemSize | number | Pixels reserved for a row that has not been laid out. Default 40. |
paddingBlockStart, paddingBlockEnd | SpaceOption | Space before the first row and after the last, from the space scale. |
getItemKey | (item: T, index: number) => Key | Stable key. Defaults to the index. |
emptyContent | ReactNode | Replaces the list when items is empty. |
onEndReached | () => void | Fires when the end scrolls into view. Paused while a loading or error row renders. |
loadingRow | ReactNode | Rendered after the last item. |
errorRow | ReactNode | Rendered after loadingRow. |
reverseOrder | boolean | Pins the newest row to the visual block end. |
scrollRegionLabel | LocalizedMessage | Name of the scroll region when it is focusable. |
ref | Ref<VirtualizedListHandle> | scrollToIndex and scrollToOffset. |
viewportRef | Ref<HTMLDivElement> | The scroll root. |
scrollToIndex(index, { align, behavior }) takes VirtualizedListAlign (Start, Center, End, Nearest). An index outside the list clamps. scrollToOffset(offset, { behavior }) scrolls to a block-axis pixel offset. A smooth behavior becomes instant when motion is reduced.
| ui-core | Write instead |
|---|---|
estimateSize={() => 64} | estimatedItemSize={64} |
renderItem={(item, index, virtualItem) => ...} | renderItem={(item, index) => ...} |
getItemKey={(index) => id} | getItemKey={(item, index) => id} |
onScrollEnd | onEndReached |
scrollableProps={{ loading, error, scrollReverse }} | loadingRow, errorRow, reverseOrder |
paddingStart / paddingEnd | paddingBlockStart / paddingBlockEnd |
scrollToIndex(i, { align: "center" }) | scrollToIndex(i, { align: VirtualizedListAlign.Center }) |
className | Style the content renderItem returns |
overscan and no VirtualItem export. A table that must unmount off-screen rows uses DataTable.
NotificationItem and Item render their own li. Set rowElement to Presentation so the list wraps each row in a presentation div and the DOM stays ul > div[role=presentation] > li:
renderItem must return exactly one list item per row.
Pass one estimatedItemSize. Rows that are taller than the estimate keep their real size after the browser lays them out. renderItem can return more content for some indexes; do not pass a per-index size function.