Skip to content

feat(web): scroll-loading and layout toggle for the server-cards widget#130

Merged
ZingerLittleBee merged 6 commits into
mainfrom
feat/dashboard-server-cards-widget
May 30, 2026
Merged

feat(web): scroll-loading and layout toggle for the server-cards widget#130
ZingerLittleBee merged 6 commits into
mainfrom
feat/dashboard-server-cards-widget

Conversation

@ZingerLittleBee
Copy link
Copy Markdown
Owner

Summary

Reworks the dashboard server-cards widget so it scales to large fleets and stops fighting the grid's fixed-height cells.

  • Content-height sizing — the widget now grows to fit its cards/rows instead of being capped at a fixed grid height (and scrolling internally).
  • Grid / list layout toggle — switchable in the widget config dialog. List mode reuses the exact /servers?view=table columns (buildServerColumns), so it is pixel-identical to the servers page; pagination footer is hidden in the widget.
  • Scroll-to-load-more — replaces the misplaced pagination footer. Renders a soft cap of 50 cards/rows up front and reveals the next batch via an IntersectionObserver sentinel 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.
  • Overlap fix — dashboard grid items carry react-grid-layout's default 0.2s transform/height transition. When a content-height widget grows (e.g. revealing more rows), its height and the translateY of 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.
  • chore(scripts) — dev scripts use localhost instead of 127.0.0.1.

Testing

Verified in Chrome DevTools with DEV-only mock servers (withMockServers, up to 500 mock + 12 real):

  • list & grid — first batch 50, scroll reveals to the full count (e.g. 212/512), spinner + "loading…" shows during load and disappears when done, no pagination footer.
  • server-cards not the last widget — inserted a widget directly below server-cards; load-more still completes fully, sentinel fires correctly through the shadcn ScrollArea (IntersectionObserver root=viewport), and the widget below stays correctly positioned.
  • overlap — dense 25ms sampling across the load transition: before the fix, the widget below overlapped the table by up to ~330px on 6/48 frames; after the fix, 0 overlapping frames in both layouts (gap stays positive throughout).

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.
@ZingerLittleBee ZingerLittleBee merged commit 4f8a62f into main May 30, 2026
2 checks passed
@ZingerLittleBee ZingerLittleBee deleted the feat/dashboard-server-cards-widget branch May 30, 2026 12:42
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.

1 participant