feat(web): recycle offscreen component rows instead of show-more paging#421
Merged
Merged
Conversation
Large SBOMs rendered the components table in 200-row "Show more" batches: reaching the tail of a 2,000-row result took nine clicks, and every revealed row stayed in the DOM for the life of the view. Render the filtered set in 100-row <tbody> chunks instead. An IntersectionObserver over the scroll container keeps chunks near the viewport live and recycles the rest into a single spacer row of their measured height, so the scrollbar geometry stays truthful while the DOM only ever holds a window. Row heights may vary (wrapping license badges, the expanded detail panel), which is why spacers use per-chunk measurements rather than a fixed row height; the chunk holding the expanded row is pinned live, and the tbody nodes are keyed by chunk index so the observer targets survive live/spacer swaps. The whole list is now reachable by plain scrolling — the show-more button and its locale keys are gone. A Playwright spec drives a 600-component scan: full set scrollable, DOM row count stays below the total at both ends of the scroll, and in-chunk row expansion still works.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Large SBOMs (server caps the detail rows at 2,000) rendered the components table in 200-row "Show more" batches — nine clicks to reach the tail, and every revealed row stayed in the DOM for the life of the view.
What
<tbody>chunks. AnIntersectionObserver(600px margin) over the table's scroll container keeps nearby chunks live and recycles offscreen ones into a single spacer row of their measured height — scrollbar geometry stays truthful while the DOM holds only a window.Verification
components-virtual.spec.ts(600-component stub): no show-more button, DOM row count < total at the top and after scrolling to the bottom (top chunks recycled), last component materializes on scroll, in-chunk row expansion works — 2/2 passtsc --noEmit, vitest 216/216, i18n en ≡ ko (529 keys), token lint — pass