CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rc-virtual-list

React Virtual List Component which worked with animation

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

scrolling.mddocs/

Scrolling

Advanced scrolling capabilities including programmatic navigation, scroll event handling, and horizontal scrolling support.

Capabilities

Scroll Event Handling

Event handlers for responding to scroll events and virtual scroll changes.

/**
 * Native scroll event handler
 * @param event - Standard React scroll event
 */
onScroll?: React.UIEventHandler<HTMLElement>;

/**
 * Virtual scroll position callback
 * @param info - Current virtual scroll position
 */
onVirtualScroll?: (info: ScrollInfo) => void;

/**
 * Callback when visible items change during scrolling
 * @param visibleList - Currently visible items
 * @param fullList - Complete data array
 */
onVisibleChange?: (visibleList: T[], fullList: T[]) => void;

interface ScrollInfo {
  /** Horizontal scroll position */
  x: number;
  /** Vertical scroll position */
  y: number;
}

Usage Examples:

import React, { useState } from "react";
import List from "rc-virtual-list";

const ScrollTrackingList = () => {
  const [scrollInfo, setScrollInfo] = useState({ x: 0, y: 0 });
  const [visibleCount, setVisibleCount] = useState(0);

  const handleVirtualScroll = (info) => {
    setScrollInfo(info);
    console.log('Virtual scroll:', info.x, info.y);
  };

  const handleVisibleChange = (visibleItems, allItems) => {
    setVisibleCount(visibleItems.length);
    console.log(`Showing ${visibleItems.length} of ${allItems.length} items`);
  };

  const handleNativeScroll = (e) => {
    console.log('Native scroll event:', e.currentTarget.scrollTop);
  };

  return (
    <div>
      <div>Position: {scrollInfo.x}, {scrollInfo.y}</div>
      <div>Visible items: {visibleCount}</div>
      
      <List
        data={data}
        height={300}
        itemHeight={50}
        itemKey="id"
        onVirtualScroll={handleVirtualScroll}
        onVisibleChange={handleVisibleChange}
        onScroll={handleNativeScroll}
      >
        {(item) => <div>{item.name}</div>}
      </List>
    </div>
  );
};

Horizontal Scrolling

Support for horizontal scrolling with custom scroll width.

/**
 * Enable horizontal scrolling with specified scroll width
 * When set, enables horizontal scrolling and virtual horizontally
 */
scrollWidth?: number;

Usage Example:

import List from "rc-virtual-list";

const HorizontalScrollList = () => {
  return (
    <List
      data={data}
      height={300}
      itemHeight={50}
      itemKey="id"
      scrollWidth={1200} // Enable horizontal scrolling
      onVirtualScroll={({ x, y }) => {
        console.log('Horizontal position:', x, 'Vertical position:', y);
      }}
    >
      {(item, index, { style, offsetX }) => (
        <div 
          style={{
            ...style,
            width: 1200, // Wide content that requires horizontal scrolling
            display: 'flex',
            alignItems: 'center'
          }}
        >
          <span style={{ minWidth: 200 }}>{item.name}</span>
          <span style={{ minWidth: 300 }}>{item.description}</span>
          <span style={{ minWidth: 150 }}>{item.category}</span>
          <span>Offset: {offsetX}px</span>
        </div>
      )}
    </List>
  );
};

Scroll Direction & RTL Support

/**
 * Text direction for right-to-left language support
 */
direction?: ScrollBarDirectionType;

type ScrollBarDirectionType = 'ltr' | 'rtl';

Usage Example:

import List from "rc-virtual-list";

const RTLList = () => {
  return (
    <List
      data={arabicData}
      height={300}
      itemHeight={50}
      itemKey="id"
      direction="rtl" // Right-to-left support
    >
      {(item) => <div dir="rtl">{item.arabicText}</div>}
    </List>
  );
};

Custom Scrollbar Styling

/**
 * Custom styles for scrollbar components
 */
styles?: {
  horizontalScrollBar?: React.CSSProperties;
  horizontalScrollBarThumb?: React.CSSProperties;
  verticalScrollBar?: React.CSSProperties;
  verticalScrollBarThumb?: React.CSSProperties;
};

/**
 * Control scrollbar visibility
 * - true: Always show scrollbars
 * - false: Never show scrollbars
 * - 'optional': Show only when needed (default)
 */
showScrollBar?: boolean | 'optional';

Usage Example:

import List from "rc-virtual-list";

const StyledScrollbarList = () => {
  const scrollbarStyles = {
    verticalScrollBar: {
      width: 12,
      backgroundColor: '#f0f0f0',
      borderRadius: 6,
    },
    verticalScrollBarThumb: {
      backgroundColor: '#666',
      borderRadius: 6,
      border: '2px solid transparent',
    },
    horizontalScrollBar: {
      height: 12,
      backgroundColor: '#f0f0f0',
      borderRadius: 6,
    },
    horizontalScrollBarThumb: {
      backgroundColor: '#666',
      borderRadius: 6,
    },
  };

  return (
    <List
      data={data}
      height={300}
      itemHeight={50}
      itemKey="id"
      scrollWidth={800}
      styles={scrollbarStyles}
      showScrollBar={true} // Always show scrollbars
    >
      {(item) => <div style={{ width: 800 }}>{item.content}</div>}
    </List>
  );
};

Scroll Alignment Options

/**
 * Alignment options for programmatic scrolling
 */
type ScrollAlign = 'top' | 'bottom' | 'auto';
  • 'top': Align the target item to the top of the viewport
  • 'bottom': Align the target item to the bottom of the viewport
  • 'auto': Smart alignment based on current position (minimal scroll distance)

Internal ScrollBar Interface

/**
 * Internal interface for scrollbar control (not directly accessible)
 */
interface ScrollBarRef {
  /** Hide scrollbar after delay */
  delayHidden: () => void;
}

This interface is used internally by the List component for scrollbar management and is not accessible to consumers.

Advanced Scroll Scenarios

Infinite Scrolling

const InfiniteScrollList = () => {
  const [data, setData] = useState(initialData);
  const [loading, setLoading] = useState(false);

  const handleVisibleChange = (visibleItems, allItems) => {
    const lastVisible = visibleItems[visibleItems.length - 1];
    const lastIndex = allItems.indexOf(lastVisible);
    
    // Load more when approaching end
    if (lastIndex > allItems.length - 10 && !loading) {
      setLoading(true);
      loadMoreData().then(newData => {
        setData(prev => [...prev, ...newData]);
        setLoading(false);
      });
    }
  };

  return (
    <List
      data={data}
      height={300}
      itemHeight={50}
      itemKey="id"
      onVisibleChange={handleVisibleChange}
    >
      {(item) => <div>{item.name}</div>}
    </List>
  );
};

Scroll Position Persistence

const PersistentScrollList = () => {
  const listRef = useRef<ListRef>(null);

  useEffect(() => {
    // Restore scroll position on mount
    const savedPosition = localStorage.getItem('listScrollPosition');
    if (savedPosition) {
      listRef.current?.scrollTo(parseInt(savedPosition));
    }
  }, []);

  const handleVirtualScroll = ({ y }) => {
    // Save scroll position
    localStorage.setItem('listScrollPosition', y.toString());
  };

  return (
    <List
      ref={listRef}
      data={data}
      height={300}
      itemHeight={50}
      itemKey="id"
      onVirtualScroll={handleVirtualScroll}
    >
      {(item) => <div>{item.name}</div>}
    </List>
  );
};

Install with Tessl CLI

npx tessl i tessl/npm-rc-virtual-list

docs

index.md

list-component.md

list-reference.md

render-system.md

scrolling.md

tile.json