Skip to content

Feature request: Virtual Scrolling for Timeline Performance #7

@panoptican

Description

@panoptican

Type: Feature Request
Priority: High

Problem:
When users accumulate thousands of screenshot events, the timeline becomes sluggish. The current implementation renders all visible events as DOM nodes, causing:

  • Slow initial load times
  • Janky scrolling
  • High memory usage
  • Poor performance on older machines

Proposed Solution:
Implement virtualized scrolling using @tanstack/react-virtual that only renders visible items plus a small overscan buffer.

Key Implementation Details:

  1. Virtual Timeline Component using useVirtualizer:
const virtualizer = useVirtualizer({
  count: items.length,
  getScrollElement: () => parentRef.current,
  estimateSize: (index) => {
    const item = items[index];
    return item?.type === "header" ? HEADER_HEIGHT : ROW_HEIGHT;
  },
  overscan: 3,
});
  1. Responsive Grid Columns via ResizeObserver:
export function useResponsiveColumns(containerRef: RefObject<HTMLElement>): number {
  const [columns, setColumns] = useState(4);

  useEffect(() => {
    const observer = new ResizeObserver((entries) => {
      const width = entries[0]?.contentRect.width ?? 0;
      if (width >= 1280) setColumns(4);
      else if (width >= 1024) setColumns(3);
      else if (width >= 768) setColumns(2);
      else setColumns(1);
    });
    observer.observe(container);
    return () => observer.disconnect();
  }, [containerRef]);

  return columns;
}
  1. Virtual Item Types (headers and rows):
type VirtualTimelineItem =
  | { type: "header"; date: string; key: string; events: Event[] }
  | { type: "row"; events: Event[]; key: string };

Benefits:

  • Constant memory usage regardless of event count
  • Smooth 60fps scrolling
  • Instant navigation between pages
  • Works with existing date-grouped layout

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions