Skip to main content
PROYECTOVIVIANA

Virtualizer

Virtualizer efficiently renders large collections by only mounting visible items. It renders no DOM of its own: wrap a collection component such as ListBox, GridList, Table, or Tree, and that collection element becomes the scroll container. It supports list, grid, waterfall, and table layouts with full keyboard navigation and drag-and-drop.

Import

import {
  Virtualizer,
  ListLayout,
  GridLayout,
  WaterfallLayout,
  TableLayout
} from '@proyecto-viviana/solidaria-components';

Basic List

A virtual list rendering 1,000 items efficiently. Only visible items are mounted in the DOM. The ListBox is the scroller, so give it the height and overflow.

Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
<Virtualizer layout={ListLayout} layoutOptions={{ itemSize: 40, overscan: 5 }}>
  <ListBox
    aria-label="Virtualized list"
    selectionMode="multiple"
    items={items}
    getKey={(item) => item.id}
    getTextValue={(item) => item.label}
    class="viewport"
    style={{ height: "256px" }}
  >
    {(item) => (
      <ListBoxOption id={item.id} textValue={item.label} class="row">
        {item.label}
      </ListBoxOption>
    )}
  </ListBox>
</Virtualizer>

Grid Layout

Display items in a fixed-column grid. GridLayout windows rows of rowHeight with columnCount items each; set layout="grid" on the ListBox so arrow keys move across columns, and lay the collection content out in the same columns.

Card 1Grid item
Card 2Grid item
Card 3Grid item
Card 4Grid item
Card 5Grid item
Card 6Grid item
Card 7Grid item
Card 8Grid item
Card 9Grid item
Card 10Grid item
Card 11Grid item
Card 12Grid item
Card 13Grid item
Card 14Grid item
Card 15Grid item
<Virtualizer layout={GridLayout} layoutOptions={{ rowHeight: 120, columnCount: 3 }}>
  <ListBox
    aria-label="Virtualized grid"
    layout="grid"
    items={items}
    getKey={(item) => item.id}
    getTextValue={(item) => item.label}
    class="viewport viewport--grid"
    style={{
      height: "320px",
      "--grid-columns": "repeat(3, minmax(0, 1fr))",
      "--grid-row-height": "120px",
    }}
  >
    {(item) => (
      <ListBoxOption id={item.id} textValue={item.label}>
        <div class="tile">{item.label}</div>
      </ListBoxOption>
    )}
  </ListBox>
</Virtualizer>

Waterfall Layout

Columns follow the available width: WaterfallLayout derives the column count from minColumnWidth and gap against the measured collection width, and windows rows of rowHeight. Match it with an auto-fill grid on the collection content.

Card 1Waterfall item
Card 2Waterfall item
Card 3Waterfall item
Card 4Waterfall item
Card 5Waterfall item
<Virtualizer
  layout={WaterfallLayout}
  layoutOptions={{ minColumnWidth: 200, gap: 8, rowHeight: 120 }}
>
  <ListBox
    aria-label="Virtualized waterfall"
    layout="grid"
    items={items}
    getKey={(item) => item.id}
    getTextValue={(item) => item.label}
    class="viewport viewport--grid"
    style={{
      height: "384px",
      "--grid-columns": "repeat(auto-fill, minmax(200px, 1fr))",
      "--grid-row-height": "120px",
      "--grid-gap": "8px",
    }}
  >
    {(item) => (
      <ListBoxOption id={item.id} textValue={item.label}>
        <div class="tile">{item.label}</div>
      </ListBoxOption>
    )}
  </ListBox>
</Virtualizer>

Virtualizer Props

Props

PropTypeDefaultDescription
layoutVirtualizerLayoutClass<O> | VirtualizerLayout<O>—Layout implementation (ListLayout, GridLayout, WaterfallLayout, TableLayout) or a custom layout object
layoutOptionsO—Options passed to the layout. Varies by layout type (e.g., itemSize for ListLayout, columnCount for GridLayout)
childrenJSX.Element—The collection to virtualize (ListBox, GridList, Table, Tree). Virtualizer renders no element; the collection element is the scroll container, so size and overflow belong on it
renderDropIndicator(index: number, position: 'before' | 'after' | 'on') => JSX.Element—Render function for drag-and-drop indicators
getDropOperation(target, types, allowedOperations) => DropOperation—Resolver for determining allowed drop operations

Layout Options

ListLayout / TableLayout

Props

PropTypeDefaultDescription
itemSizenumber40Height of each row in pixels
overscannumber5Number of extra items to render beyond the visible area

GridLayout

Props

PropTypeDefaultDescription
rowHeightnumber—Height of each row in pixels
columnCountnumber—Number of columns in the grid

WaterfallLayout

Props

PropTypeDefaultDescription
minColumnWidthnumber200Minimum width of each column. The column count is derived from it and the measured collection width.
gapnumber0Horizontal gap between columns in pixels, counted when deriving the column count
rowHeightnumber—Height of each row in pixels

Context

Child components can access virtualizer state via useVirtualizerContext(). This provides getVisibleRange(), getLayoutInfo(), and drop target resolution for building custom virtualized collection components.

Accessibility

  • Keyboard navigation works seamlessly across virtualized items using aria-activedescendant
  • Focus management preserves scroll position when items are focused via keyboard
  • Screen readers announce the total item count and current position
  • Drag and drop indicators are announced to assistive technologies
  • Integrates with ListBox, Table, GridList, and Tree for full a11y support