fix(dashboard): replace GridStack with dnd-kit + CSS Grid bento#104
Merged
Conversation
GridStack sized each widget from .grid-stack-item-content's firstElementChild,
which in widget-shell is the absolute-positioned action toolbar (~24px), not the
body. Every card collapsed to one 86px row and its real content was clipped
behind overflow:hidden; sizeToContent made it worse (one-shot measure vs async
React Query content).
Replace GridStack with a content-driven CSS Grid bento: row heights come from
content (no JS measurement, no clipping), dnd-kit handles reorder, and per-type
col/row span footprints keep adjacent unequal cards aligned. Drop the gridstack
dependency and all gridstack CSS.
Widget store moves from GridStack {x,y,w,h} layouts to a colSpan/rowSpan
footprint model (persist v3 migration drops legacy fields). Tests rewritten to
the new contract; new widget-bento.spec asserts no widget clips its content.
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.
Problem
OIL Board widgets clipped their content (internal scrollbars, dead space). The "morning fix" (`sizeToContent: true`) made it worse: every card collapsed to one 86px row with content hidden underneath.
Root cause (proven against gridstack 12.6.0 source)
`GridStack.resizeToContent` measures `.grid-stack-item-content`'s `firstElementChild` and assumes a single content child. In `widget-shell.tsx` that first child is the absolute-positioned action toolbar (~24px), not the body, so GridStack sized every widget to ~1 row and `overflow: hidden` clipped the rest. GridStack also never re-measures when async React Query content loads (its only ResizeObserver watches the grid for width changes).
This is a model mismatch: fixed-row grids (GridStack, react-grid-layout) treat content-hugging as a fragile bolt-on.
Fix
Drop GridStack. Content-driven CSS Grid bento + dnd-kit:
Store moves from GridStack `{x,y,w,h}` to a `colSpan`/`rowSpan` footprint model (persist v3 migration drops legacy fields).
Tests (TDD)
Design doc
`docs/superpowers/specs/2026-06-07-widget-dashboard-bento-design.md`
Note on local full-suite run
Full `pnpm test:e2e` locally shows 16 failures unrelated to this change and pre-existing: timezone off-by-one (machine is JST, config pins no `timezoneId`, e.g. issue due-date "Jun 15" -> "Jun 14"), plus email-backend / guest-share-token / service-role / inbox env cases. All are in share/auth/inbox/rbac/email/issue-detail paths, none reachable from dashboard widget code or `.widget-grid` CSS. They pass in UTC CI.