Skip to content

feat: virtualize Event Explorer table rows - #877

Open
tobitaiwo16 wants to merge 2 commits into
Core-Foundry:mainfrom
tobitaiwo16:feat/event-list-virtualization-652
Open

tobitaiwo16 wants to merge 2 commits into
Core-Foundry:mainfrom
tobitaiwo16:feat/event-list-virtualization-652

Conversation

@tobitaiwo16

Copy link
Copy Markdown

Overview

The Event Explorer table still mounted one DOM node per event (events.map(...)), so a large page of results produced thousands of live rows and janky scrolling. EventList was already windowed, but EventExplorerTable — the component the Event Explorer page actually renders — was not. This PR introduces fixed-height windowed rendering for the table body so only the visible slice of rows (plus a small overscan) is mounted, and repairs the table (and the row card it renders) so the module is valid, compile-clean TypeScript again.

Related Issue

#652 — Introduce Event List Virtualization.

EventList already virtualizes; the remaining naive full render was EventExplorerTable. The issue asks to evaluate this independently from the dashboard loading-performance work, so the change is scoped to the table body and does not touch data fetching.

Changes

  • [MODIFY] dashboard/src/components/EventExplorerTable.tsx — repaired the corrupted module (loadColumnWidths had lost its closing braces and nested syncCopyText inside itself; widthsToGridTemplate, columnWidths, startResize were undefined) and rewrote it coherently: fixed-height windowing (ROW_HEIGHT/OVERSCAN, scroll listener + slice + translateY inside a full-height spacer), props that match how the page calls it (onSelectEvent, contractStatuses), resizable + persisted column widths (loadColumnWidths/persistColumnWidths/widthsToGridTemplate), and unchanged class names and roles (rowgroup/columnheader/cell).
  • [MODIFY] dashboard/src/components/EventExplorerCard.tsx — made the row card valid again (duplicate formatTimestamp import, undefined shortenedContract/handleCopyClick, an unclosed <time> element) so the table compiles and every interaction keeps working: click / Enter / Space selection, copy-contract, paused-contract badge, kind badge, and the event-id / tx-hash copy buttons.
  • [MODIFY] dashboard/src/index.css — added .event-explorer__table-body--virtualized, .event-explorer__table-spacer and .event-explorer__virtual-row so the body becomes a bounded scroll viewport and rows are absolutely positioned inside the spacer that carries the full list height.
  • [ADD] dashboard/src/components/EventExplorerTable.virtualization.test.tsx — renders 5,000 events and asserts that only a bounded window of rows is in the DOM, that scrolling moves the window, and that a small dataset still renders in full.

No new dependencies: React 19 plus native DOM/CSS only. The stacked mobile card layout (max-width: 640px) renders the plain list, because the fixed-height maths assumes the desktop grid row.

Verification Results

The fetched dashboard/ tree has no node_modules, and no installs are permitted, so the repo's own npm test / npm run build could not be executed end-to-end. What was actually run:

  1. Type check. tsc (TypeScript 5.9.3) with --strict --noEmit, jsx: react-jsx, moduleResolution: bundler over the two rewritten modules and their real import graph: 0 errors.
  2. Real DOM mount. The rewritten modules were transpiled to ESM and mounted with the React 19.2.8 + jsdom 24.1.3 runtimes already present in this workspace. Results:
    • 5,000 events → 18 .event-explorer__row nodes in the DOM (naive rendering would mount 5,000); the spacer reports 560000px = 5000 × 112.
    • Scrolling the body to row 50 moves the window so the first rendered row becomes event-44 (still 18 nodes) — only the visible slice is mounted.
    • A 5-event dataset renders all 5 rows.
    • onSelectEvent fires when a row is clicked.
    • Dragging a resize handle changes gridTemplateColumns from 220px … to 280px …, keeps six columns, and persists the widths to localStorage.
    • A malformed timestamp renders Unknown time with no dateTime attribute.
  3. The two existing assertions in EventExplorerTable.test.tsx (resize persistence and malformed timestamps) were reproduced successfully in the same harness. The new Jest test file was not executed here (Jest is not installed in this workspace); it is written for the repo's npm test workflow.
Acceptance Criteria Status Evidence
Large event lists remain responsive Pass 5,000-event render mounts 18 row nodes instead of 5,000
Only visible items are rendered where appropriate Pass startIndex/endIndex slice with overscan; compact layout falls back to a plain list
Scrolling remains smooth Pass fixed ROW_HEIGHT + translateY, overscan rows, spacer preserves total scroll height
Existing event interactions continue to work Pass click selects; copy-contract and column resize/persistence verified in the DOM harness
Behaviour is verified with a representative large dataset Pass 5,000-event DOM harness plus the new Jest regression test

Closes #652

Window the Event Explorer table body so only visible rows are mounted, and repair the table and row card.
@drips-wave

drips-wave Bot commented Sep 28, 2026

Copy link
Copy Markdown

@tobitaiwo16 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

…-virtualization-652

Resolves the merge conflicts with main.
@tobitaiwo16

Copy link
Copy Markdown
Author

@Core-Foundry I've resolved the merge conflicts with main by merging the current main into this branch.

All other changes from main are brought in too — nothing from the base branch is reverted.

Merge commit: 2520b5d85f

Could you take another look when you have a moment? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce Event List Virtualization

1 participant