Skip to content

feat: virtual scrolling for gallery grid view#3170

Open
msedek wants to merge 1 commit intorommapp:masterfrom
msedek:pr/gallery-virtual-scroll
Open

feat: virtual scrolling for gallery grid view#3170
msedek wants to merge 1 commit intorommapp:masterfrom
msedek:pr/gallery-virtual-scroll

Conversation

@msedek
Copy link
Copy Markdown

@msedek msedek commented Mar 24, 2026

Summary

Implements row-based virtual scrolling for the gallery card grid using @tanstack/vue-virtual, addressing the performance issue described in #1426 and #3161.

Problem

When browsing a platform with 1000+ ROMs, the infinite scroll keeps appending GameCard components to the DOM. After scrolling 500+ cards (~25,000 DOM nodes), clicking a game freezes the browser as Vue destroys all components at once.

Solution

  • Replace the flat v-for over filteredRoms with useWindowVirtualizer from @tanstack/vue-virtual
  • ROMs are grouped into rows based on responsive column count (derived from Vuetify breakpoints + view settings)
  • Only visible rows + 5 overscan rows are rendered in DOM
  • At 1000 ROMs with 6 columns: ~60 cards in DOM instead of 1000

What changed

  • frontend/src/views/Gallery/Platform.vue — template and script
  • frontend/package.json — added @tanstack/vue-virtual dependency

What didn't change

  • ROM store, GameCard component, infinite scroll fetch logic, selection logic — all untouched
  • List/table view (currentView == 2) — unchanged

Test plan

  • Browse a platform with 1000+ ROMs — should render smoothly
  • Scroll through all ROMs — only visible cards in DOM (inspect Elements tab)
  • Click a game after scrolling 500+ cards — instant navigation, no freeze
  • Responsive: resize window — columns adjust correctly
  • View switching (small/big/list) — all views work
  • Multi-select with shift-click — selection logic preserved

Tested with 5,600 ROMs across 12 platforms (largest: NES with 1,366 ROMs).

AI-assisted: Claude was used for research and implementation.

Closes #3161

Replace v-for over all ROMs with @tanstack/vue-virtual window
virtualizer. Only visible rows + 5 overscan are rendered in DOM.
At 1000 ROMs with 6 columns, only ~60 cards exist in DOM instead
of 1000. Dramatically reduces freeze when navigating away.

AI-assisted: Claude was used for research and implementation.
Copy link
Copy Markdown
Member

@zurdi15 zurdi15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the Typescript check

Also, is it possible for you to sign the commit? It's OK otherwise

@gantoine gantoine added the on-hold Pending further research or blocked by another issue label Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

on-hold Pending further research or blocked by another issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Performance] Virtual scrolling for gallery grid view using @tanstack/vue-virtual

3 participants