Virtuoso Documentation

website·Indexed 34 days ago

https://virtuoso.dev

Documentation for Virtuoso, a suite of React components for rendering large datasets. Includes react-virtuoso for virtualized lists with variable-sized items, a high-performance Data Table with support for column resizing, reordering, and sticky columns, and a specialized Message List for chat-like interfaces with imperative scrolling and item identity management.

Tokens
104.1K
Snippets
435
Records
660
Agent score
71%

What's inside Virtuoso

  1. Overview of Virtuoso Data Table

    @virtuoso.dev/data-table is a virtualized React data table designed for high-performance rendering of large datasets. It provides row and column virtualization, support for grouped data, sticky columns, state persistence, and interactive column features such as resizing, reordering, and visibility toggling. It serves as the successor to TableVirtuoso for users who require a dedicated table-specific API rather than a general virtualized HTML table primitive.
  2. Overview of Virtuoso Agent Skills

    Virtuoso packages provide Agent Skills—structured guidance designed to teach coding agents how to use the libraries correctly. These skills prevent agents from relying on outdated training data or habits from other virtualization libraries by providing component selection rules, measurement constraints, common pitfalls, and full package documentation.

    Available skills include:

    • react-virtuoso: Covers virtualized lists, grids, and tables (Virtuoso, GroupedVirtuoso, VirtuosoGrid, TableVirtuoso).
    • message-list: Covers chat and AI conversation UIs (VirtuosoMessageList).
    • data-table: Covers the virtualized data grid (@virtuoso.dev/data-table).
    • reactive-engine: Covers the @virtuoso.dev/reactive-engine-* state management family.
  3. Overview of Virtuoso Masonry

    Virtuoso Masonry is a virtualized masonry layout component for React. It is designed to arrange items in a grid with varying heights while maintaining high performance for large datasets by only rendering visible items. Key features include:

    • Virtualized rendering for optimal performance.
    • Support for variable item heights (automatically measured and arranged).
    • Dynamic column counts based on screen or container width.
    • Support for using the window as the scroll container.
    • Just-in-time distribution of items to columns during scrolling.
  4. Overview of Virtuoso Message List

    Virtuoso Message List is a virtualized React component built for human/chatbot conversations. It optimizes performance for large message histories by rendering only visible items. Key features include:

    • Declarative scroll control: Update scroll positions via a data property with optional smooth animation.
    • Automatic scrolling: Configurable behavior for scrolling when new messages arrive or update.
    • Customizable UI: Supports custom headers, footers, sticky elements, loading indicators, and scroll-to-bottom buttons.
    • Flexible positioning: Controls vertical positioning for conversations that do not fill the viewport.
    • Unstyled: Designed to integrate easily with any design system or UI library.
  5. Overview of Gurx reactive state management

    Gurx is a TypeScript-native reactive state management library designed for complex web applications where the store object and component tree lack symmetry. It uses a push-based recalculation model where data flows through pipes of functional operators to reduce UI re-renders. The library is type-safe, optimized to push updates only when values change, and allows for unit testing by interacting with nodes outside of React.
  6. Implement a basic @virtuoso.dev/data-table structure

    The new data-table architecture requires a data model (created via localModel) and a declarative column structure using DataTableColumn, DataTableColumnHeader, and DataTableCell.
    import { DataTable, DataTableCell, DataTableColumn, DataTableColumnHeader } from '@/components/ui/data-table'
    import { localModel } from '@virtuoso.dev/data-table'
    
    const rows = Array.from({ length: 40 }, (_, index) => ({
      id: `SKU-${String(index + 1).padStart(3, '0')}`,
      name: `Product ${index + 1}`,
      category: ['Office', 'Peripherals', 'Audio'][index % 3]!,
      status: ['In stock', 'Low stock', 'Backorder'][index % 3]!,
    }))
    
    const model = localModel({ data: rows })
    
    export default function App() {
      return (
        <DataTable 
          className="rounded-xl" 
          computeRowKey={({ data }) => data.id} 
          model={model} 
          style={{ height: 340 }}
        >
          <DataTableColumn field="name">
            <DataTableColumnHeader>Name</DataTableColumnHeader>
            <DataTableCell>
              {({ row }) => (
                <div className="flex flex-col">
                  <span className="font-medium">{row.data.name}</span>
                  <span className="text-xs text-muted-foreground">{row.data.id}</span>
                </div>
              )}
            </DataTableCell>
          </DataTableColumn>
          
          <DataTableColumn field="category">
            <DataTableColumnHeader>Category</DataTableColumnHeader>
            <DataTableCell>{({ cellValue }) => String(cellValue)}</DataTableCell>
          </DataTableColumn>
          
          <DataTableColumn field="status" sticky="right">
            <DataTableColumnHeader>Status</DataTableColumnHeader>
            <DataTableCell>{({ cellValue }) => String(cellValue)}</DataTableCell>
          </DataTableColumn>
        </DataTable>
      )
    }
  7. Understand DataTable column width and layout

    Column width in the DataTable consists of two parts: the base width and the realized width.

    1. Base Width: Determined by measuring the DataTableColumnHeader. This width serves as the starting point for both the header and every body cell in that column.
    2. Realized Width: The final width after the table compares total base widths against the viewport.
      • If the viewport is wider than the total base width, extra space is distributed based on grow settings.
      • If the viewport is narrower, columns maintain their base widths and the table enables horizontal scrolling.
  8. Track list position using ListScrollLocation

    The ListScrollLocation type provides detailed metrics about the list's position relative to the viewport and the scroll element. This is useful for implementing 'scroll to bottom' logic or detecting when the user has reached the end of the list.
    interface ListScrollLocation {
      bottomOffset: number; // Distance between scroller bottom edge and viewport bottom edge (0 = at bottom)
      isAtBottom: boolean; // True if list is at the bottom or currently scrolling to the bottom
      lastItemBottomOffset: number; // Pixel distance from last visible item bottom edge to viewport bottom
      lastVisibleItemIndex: number; // Index of the bottom-most item visible in the viewport
      listOffset: number; // Distance between list top edge and viewport top edge (negative when scrolling down)
      scrollHeight: number; // Total scroll height of the scroller wrapper
      visibleListHeight: number; // Height of the visible list portion excluding headers/footers
    }
  9. Implement a virtualized grid with VirtuosoGrid

    VirtuosoGrid is a virtualized grid component designed for efficiently rendering large datasets in grid or masonry layouts. It automatically calculates visible items based on the container and item dimensions, ensuring only the necessary elements are rendered in the DOM.
    <VirtuosoGrid
      totalCount={1000}
      itemContent={(index) => <div className="grid-item">Item {index}</div>}
      listClassName="grid-container"
    />
  10. Understand the shadcn wrapper architecture

    The @virtuoso.dev/data-table installation via shadcn splits the library into two parts: a wrapper and a headless package.

    • The Wrapper (@/components/ui/data-table): This is code copied into your repository. It owns the presentation layer, including Tailwind classes, default components (rows, headers, loading states), and ergonomic component names. You can edit these files directly to change the look and feel without affecting the table's logic.
    • The Headless Package (@virtuoso.dev/data-table): This is the installed dependency that owns the behavior, including virtualization, scrolling, the reactive engine, and data models (localModel, remoteModel).
    import { DataTable, DataTableCell, DataTableColumn, DataTableColumnHeader } from '@/components/ui/data-table'
    import { localModel } from '@virtuoso.dev/data-table'
    
    const rows = [
      { product: 'Standing Desk', owner: 'Avery', status: 'Launch ready' },
      { product: 'USB-C Dock', owner: 'Morgan', status: 'In review' },
      { product: 'Mechanical Keyboard', owner: 'Riley', status: 'Backorder' },
    ]
    
    const model = localModel({ data: rows })
    
    export default function App() {
      return (
        <DataTable model={model} style={{ height: 280 }}>
          <DataTableColumn field="product">
            <DataTableColumnHeader>Product</DataTableColumnHeader>
            <DataTableCell className="font-medium">{({ cellValue }) => String(cellValue)}</DataTableCell>
          </DataTableColumn>
          <DataTableColumn field="owner">
            <DataTableColumnHeader>Owner</DataTableColumnHeader>
            <DataTableCell>{({ cellValue }) => String(cellValue)}</DataTableCell>
          </DataTableColumn>
          <DataTableColumn field="status">
            <DataTableColumnHeader>Status</DataTableColumnHeader>
            <DataTableCell>
              {({ cellValue }) => <span className="rounded-full bg-muted px-2 py-1 text-xs font-medium">{String(cellValue)}</span>}
            </DataTableCell>
          </DataTableColumn>
        </DataTable>
      )
    }
  11. Use Cell and Header render parameters

    Render functions for cells and headers receive a parameter object providing context about the current row and column.

    Cell Render Parameters (CellRenderParams):

    • cellValue: The value of the field for the current row (or result of an accessor).
    • row: The full virtualized row object; use row.data for multi-field dependencies.
    • column: The column definition.
    • columnKey: Internal key for the column instance.
    • columnState: Runtime state (e.g., { sticky: boolean }).
    • overlaidByScrollbar: Boolean indicating if a native OS scrollbar overlaps the cell edge.

    Header Render Parameters (ColumnHeaderRenderParams): Includes all the above except cellValue and row.

    type CellRenderParams = {
      cellValue: unknown
      row: RowItem
      column: ColumnDefinition
      columnKey: string
      columnState: ColumnState // e.g., { sticky: boolean }
      overlaidByScrollbar: boolean
    }
    
    type ColumnHeaderRenderParams = Omit<CellRenderParams, 'cellValue' | 'row'>
  12. Render grouped tabular data with GroupedTableVirtuoso

    GroupedTableVirtuoso is a virtualized table component designed for hierarchical data. It allows rendering grouped tabular data with sticky group headers, combining the functionality of TableVirtuoso with group support.
    <GroupedTableVirtuoso
      groupCounts={[10, 20, 15]}
      groupContent={(index) => (
        <td colSpan={2}>Group {index}</td>
      )}
      itemContent={(index, groupIndex) => (
        <>
          <td>Item {index}</td>
          <td>Group {groupIndex}</td>
        </>
      )}
    />