feat(web): scroll-loading and layout toggle for the server-cards widget#130
Merged
Conversation
Switch the server-cards widget from the fixed-height 'free' sizing strategy to 'content-height' so the grid cell grows with the number of cards instead of capping at a fixed height and scrolling. Drop the inner h-full/overflow-auto and tag the grid container with data-measure so the dashboard grid measures the natural content height.
Add a layout switch (grid/list) to the server-cards widget config dialog. The new list layout reuses the servers page table verbatim — the column definitions are extracted into a shared buildServerColumns() consumed by both /servers?view=table and the widget — so the two render identically. The widget builds the table with local (non-URL-synced) state, no pagination, and hides the selection/actions/group/status-dot columns.
The list layout reused the servers DataTable, which surfaced a page-level pagination footer inside the widget — wrong for a content-sized dashboard tile (the footer also mis-reported pages since rows were never paginated). Add a hidePagination prop to DataTable and use it here. Replace pagination with incremental reveal: render the first 50 servers and load the next batch as the dashboard scrolls near the widget bottom (page-scroll driven via IntersectionObserver, compatible with the content-height sizing — no inner scroll container). The grid layout gets the same batching plus content-visibility:auto so off-screen cards skip layout/paint. Applies to both grid and list layouts.
Replace the bare scroll sentinel with a spinner + localized loading label so both grid and list layouts show a loading… indicator at the bottom while more servers reveal on scroll. Inject DEV-only mock servers into the dashboard route to exercise the incremental reveal at scale.
Dashboard grid items carry react-grid-layout's default 0.2s transform/height transition. When a content-height widget grows (e.g. the server-cards widget revealing more rows on scroll), its height and the translateY of the items below animate on slightly different timelines, so the growing widget briefly overlaps the widget beneath it. Disable the transition outside edit mode so content-driven height changes apply in a single frame; keep it while editing for drag/resize reflow.
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.
Summary
Reworks the dashboard server-cards widget so it scales to large fleets and stops fighting the grid's fixed-height cells.
/servers?view=tablecolumns (buildServerColumns), so it is pixel-identical to the servers page; pagination footer is hidden in the widget.IntersectionObserversentinel as the dashboard scrolls near the widget bottom (page-scroll driven, compatible with content-height). A spinner + localized "loading…" label shows at the bottom of both grid and list while more remain.0.2s transform/heighttransition. When a content-height widget grows (e.g. revealing more rows), its height and thetranslateYof the items below animate on slightly different timelines, so the growing widget briefly overlaps the one beneath it. Disable the transition outside edit mode so content-driven height changes apply in a single frame; keep it while editing for drag/resize reflow.localhostinstead of127.0.0.1.Testing
Verified in Chrome DevTools with DEV-only mock servers (
withMockServers, up to 500 mock + 12 real):ScrollArea(IntersectionObserver root=viewport), and the widget below stays correctly positioned.