CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-virtualized

React components for efficiently rendering large lists and tabular data

Pending
Overview
Eval results
Files

navigation-components.mddocs/

Navigation and Interaction Components

Components that add keyboard navigation, scroll synchronization, and window scrolling capabilities.

Capabilities

ArrowKeyStepper Component

Higher-order component that adds arrow key navigation to virtualized components, enabling keyboard-driven scrolling.

/**
 * Adds arrow key navigation to virtualized components
 * @param props - ArrowKeyStepper configuration
 */
function ArrowKeyStepper(props: {
  /** Function that renders the navigable component */
  children: (params: {
    onSectionRendered: (params: {columnStartIndex: number, columnStopIndex: number, rowStartIndex: number, rowStopIndex: number}) => void,
    scrollToColumn: number,
    scrollToRow: number
  }) => React.Node;
  /** Optional CSS class name */
  className?: string;
  /** Total number of columns */
  columnCount: number;
  /** Whether arrow key navigation is disabled */
  disabled?: boolean;
  /** Whether the component is controlled externally */
  isControlled?: boolean;
  /** Navigation mode: 'cells' for cell-by-cell, 'edges' for visible edge navigation */
  mode?: 'cells' | 'edges';
  /** Callback when scroll position changes */
  onScrollToChange?: (params: {scrollToColumn: number, scrollToRow: number}) => void;
  /** Total number of rows */
  rowCount: number;
  /** Column index to scroll to */
  scrollToColumn?: number;
  /** Row index to scroll to */
  scrollToRow?: number;
}): React.Component;

Usage Examples:

import React, { useState } from 'react';
import { ArrowKeyStepper, Grid, AutoSizer } from 'react-virtualized';

// Basic arrow key navigation with Grid
function NavigableGrid({ data }) {
  const cellRenderer = ({ columnIndex, key, rowIndex, style }) => (
    <div key={key} style={style} className="grid-cell">
      {data[rowIndex][columnIndex]}
    </div>
  );

  return (
    <div style={{ height: 400, width: 600 }}>
      <ArrowKeyStepper
        columnCount={data[0].length}
        rowCount={data.length}
        mode="cells"
      >
        {({ onSectionRendered, scrollToColumn, scrollToRow }) => (
          <AutoSizer>
            {({ height, width }) => (
              <Grid
                cellRenderer={cellRenderer}
                columnCount={data[0].length}
                columnWidth={100}
                height={height}
                onSectionRendered={onSectionRendered}
                rowCount={data.length}
                rowHeight={50}
                scrollToColumn={scrollToColumn}
                scrollToRow={scrollToRow}
                width={width}
              />
            )}
          </AutoSizer>
        )}
      </ArrowKeyStepper>
    </div>
  );
}

// Controlled arrow key navigation with external state
function ControlledNavigableGrid({ data, onPositionChange }) {
  const [scrollToColumn, setScrollToColumn] = useState(0);
  const [scrollToRow, setScrollToRow] = useState(0);

  const handleScrollToChange = ({ scrollToColumn, scrollToRow }) => {
    setScrollToColumn(scrollToColumn);
    setScrollToRow(scrollToRow);
    onPositionChange?.(scrollToRow, scrollToColumn);
  };

  const cellRenderer = ({ columnIndex, key, rowIndex, style }) => {
    const isSelected = columnIndex === scrollToColumn && rowIndex === scrollToRow;
    
    return (
      <div
        key={key}
        style={{
          ...style,
          backgroundColor: isSelected ? '#e3f2fd' : 'white',
          border: isSelected ? '2px solid #2196f3' : '1px solid #ddd'
        }}
        className="grid-cell"
      >
        {data[rowIndex][columnIndex]}
      </div>
    );
  };

  return (
    <div>
      <div className="position-indicator">
        Current Position: Row {scrollToRow + 1}, Column {scrollToColumn + 1}
      </div>
      
      <div style={{ height: 400, width: 600 }}>
        <ArrowKeyStepper
          columnCount={data[0].length}
          rowCount={data.length}
          isControlled={true}
          scrollToColumn={scrollToColumn}
          scrollToRow={scrollToRow}
          onScrollToChange={handleScrollToChange}
          mode="cells"
        >
          {({ onSectionRendered }) => (
            <Grid
              cellRenderer={cellRenderer}
              columnCount={data[0].length}
              columnWidth={80}
              height={400}
              onSectionRendered={onSectionRendered}
              rowCount={data.length}
              rowHeight={40}
              scrollToColumn={scrollToColumn}
              scrollToRow={scrollToRow}
              width={600}
            />
          )}
        </ArrowKeyStepper>
      </div>
    </div>
  );
}

ScrollSync Component

Synchronizes scrolling between multiple virtualized components, useful for creating interfaces with linked scrollable areas.

/**
 * Synchronizes scrolling between multiple components
 * @param props - ScrollSync configuration
 */
function ScrollSync(props: {
  /** Function that renders synchronized scrollable components */
  children: (params: {
    clientHeight: number,
    clientWidth: number,
    onScroll: (params: {clientHeight: number, clientWidth: number, scrollHeight: number, scrollLeft: number, scrollTop: number, scrollWidth: number}) => void,
    scrollHeight: number,
    scrollLeft: number,
    scrollTop: number,
    scrollWidth: number
  }) => React.Node;
}): React.Component;

Usage Examples:

import React from 'react';
import { ScrollSync, Grid, List, AutoSizer } from 'react-virtualized';

// Synchronized scrolling between header and data grid
function SynchronizedTable({ headers, data }) {
  const headerRenderer = ({ columnIndex, key, style }) => (
    <div key={key} style={style} className="header-cell">
      {headers[columnIndex]}
    </div>
  );

  const cellRenderer = ({ columnIndex, key, rowIndex, style }) => (
    <div key={key} style={style} className="data-cell">
      {data[rowIndex][columnIndex]}
    </div>
  );

  return (
    <div style={{ height: 400, width: 800 }}>
      <ScrollSync>
        {({ clientHeight, clientWidth, onScroll, scrollLeft, scrollTop }) => (
          <div>
            {/* Fixed header */}
            <div style={{ height: 50, width: clientWidth }}>
              <Grid
                cellRenderer={headerRenderer}
                columnCount={headers.length}
                columnWidth={150}
                height={50}
                rowCount={1}
                rowHeight={50}
                scrollLeft={scrollLeft}
                width={clientWidth}
              />
            </div>
            
            {/* Scrollable data */}
            <div style={{ height: 350, width: clientWidth }}>
              <Grid
                cellRenderer={cellRenderer}
                columnCount={headers.length}
                columnWidth={150}
                height={350}
                onScroll={onScroll}
                rowCount={data.length}
                rowHeight={40}
                width={clientWidth}
              />
            </div>
          </div>
        )}
      </ScrollSync>
    </div>
  );
}

// Multi-panel synchronized scrolling
function MultiPanelView({ leftData, rightData }) {
  const leftCellRenderer = ({ key, rowIndex, style }) => (
    <div key={key} style={style} className="left-cell">
      {leftData[rowIndex]}
    </div>
  );

  const rightCellRenderer = ({ key, rowIndex, style }) => (
    <div key={key} style={style} className="right-cell">
      {rightData[rowIndex]}
    </div>
  );

  return (
    <div style={{ height: 500, width: '100%' }}>
      <ScrollSync>
        {({ onScroll, scrollTop }) => (
          <AutoSizer>
            {({ height, width }) => (
              <div style={{ display: 'flex', height, width }}>
                {/* Left panel */}
                <div style={{ width: width * 0.3 }}>
                  <List
                    height={height}
                    onScroll={onScroll}
                    rowCount={leftData.length}
                    rowHeight={60}
                    rowRenderer={leftCellRenderer}
                    scrollTop={scrollTop}
                    width={width * 0.3}
                  />
                </div>
                
                {/* Right panel */}
                <div style={{ width: width * 0.7 }}>
                  <List
                    height={height}
                    onScroll={onScroll}
                    rowCount={rightData.length}
                    rowHeight={60}
                    rowRenderer={rightCellRenderer}
                    scrollTop={scrollTop}
                    width={width * 0.7}
                  />
                </div>
              </div>
            )}
          </AutoSizer>
        )}
      </ScrollSync>
    </div>
  );
}

WindowScroller Component

Enables virtualized components to be scrolled by the browser window instead of an internal scrollable container.

/**
 * Enables window-based scrolling for components
 * @param props - WindowScroller configuration
 */
function WindowScroller(props: {
  /** Function that renders the window-scrollable component */
  children: (params: {
    height: number,
    isScrolling: boolean,
    onChildScroll: (params: {scrollTop: number}) => void,
    scrollTop: number,
    width: number
  }) => React.Node;
  /** Callback when window resizes */
  onResize?: (params: {height: number, width: number}) => void;
  /** Callback when window scrolls */
  onScroll?: (params: {scrollTop: number}) => void;
  /** Custom scroll element (defaults to window) */
  scrollElement?: Element;
  /** Server-side rendering flag */
  serverHeight?: number;
  /** Server-side rendering flag */
  serverWidth?: number;
}): React.Component;

/** Default timeout for scroll detection */
const IS_SCROLLING_TIMEOUT: number;

Usage Examples:

import React from 'react';
import { WindowScroller, List, AutoSizer } from 'react-virtualized';

// Basic window scrolling list
function WindowScrolledList({ items }) {
  const rowRenderer = ({ index, key, style }) => (
    <div key={key} style={style} className="list-item">
      <h3>Item {index}</h3>
      <p>{items[index]}</p>
    </div>
  );

  return (
    <WindowScroller>
      {({ height, isScrolling, onChildScroll, scrollTop, width }) => (
        <AutoSizer disableHeight>
          {({ width: autoWidth }) => (
            <List
              autoHeight
              height={height}
              isScrolling={isScrolling}
              onScroll={onChildScroll}
              rowCount={items.length}
              rowHeight={120}
              rowRenderer={rowRenderer}
              scrollTop={scrollTop}
              width={autoWidth}
            />
          )}
        </AutoSizer>
      )}
    </WindowScroller>
  );
}

// Window scrolling with header and footer
function FullPageList({ items, headerContent, footerContent }) {
  const rowRenderer = ({ index, key, style }) => (
    <div key={key} style={style} className="full-page-item">
      <div className="item-content">
        <h4>{items[index].title}</h4>
        <p>{items[index].description}</p>
        <div className="item-meta">
          <span>{items[index].date}</span>
          <span>{items[index].author}</span>
        </div>
      </div>
    </div>
  );

  return (
    <div>
      {/* Page header */}
      <header style={{ height: 80, padding: 20, backgroundColor: '#f5f5f5' }}>
        {headerContent}
      </header>

      {/* Window-scrolled content */}
      <WindowScroller>
        {({ height, isScrolling, onChildScroll, scrollTop, width }) => (
          <div style={{ width: '100%' }}>
            <List
              autoHeight
              height={height}
              isScrolling={isScrolling}
              onScroll={onChildScroll}
              rowCount={items.length}
              rowHeight={150}
              rowRenderer={rowRenderer}
              scrollTop={scrollTop}
              width={width}
              style={{ outline: 'none' }}
            />
          </div>
        )}
      </WindowScroller>

      {/* Page footer */}
      <footer style={{ height: 60, padding: 20, backgroundColor: '#f5f5f5' }}>
        {footerContent}
      </footer>
    </div>
  );
}

// Window scrolling with scroll monitoring
function MonitoredWindowList({ items, onScrollChange }) {
  const handleScroll = ({ scrollTop }) => {
    onScrollChange?.(scrollTop);
  };

  const handleResize = ({ height, width }) => {
    console.log(`Window resized to ${width}x${height}`);
  };

  const rowRenderer = ({ index, key, style }) => (
    <div key={key} style={style} className="monitored-item">
      <div className="item-number">#{index + 1}</div>
      <div className="item-body">
        <h3>{items[index].title}</h3>
        <p>{items[index].content}</p>
      </div>
    </div>
  );

  return (
    <div className="page-container">
      <div className="content-header">
        <h1>Scrollable Content</h1>
        <p>This list scrolls with the browser window</p>
      </div>

      <WindowScroller
        onScroll={handleScroll}
        onResize={handleResize}
      >
        {({ height, isScrolling, onChildScroll, scrollTop, width }) => (
          <div style={{ maxWidth: 800, margin: '0 auto' }}>
            <List
              autoHeight
              height={height}
              isScrolling={isScrolling}
              onScroll={onChildScroll}
              rowCount={items.length}
              rowHeight={100}
              rowRenderer={rowRenderer}
              scrollTop={scrollTop}
              width={Math.min(width, 800)}
            />
          </div>
        )}
      </WindowScroller>
    </div>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-react-virtualized

docs

core-components.md

dynamic-content.md

index.md

layout-components.md

navigation-components.md

specialized-layouts.md

table-components.md

utilities.md

tile.json