feat(dashboard): show a snap grid while dragging or resizing a tile#2715
feat(dashboard): show a snap grid while dragging or resizing a tile#2715alex-fedotyev wants to merge 4 commits into
Conversation
Draw the grid a tile snaps to while it is being dragged or resized, and highlight the cells around the tile's current position so the drop target is clear. The overlay is a drop-in wrapper (SnapGridLayout) around WidthProvider(ReactGridLayout) that renders GridSnapOverlay during a drag/resize and hides it on drop. Cell geometry mirrors react-grid-layout (computeSnapCells), so the guides line up with where a tile actually lands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 188cd73 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🟡 Tier 3 — StandardIntroduces new logic, modifies core functionality, or touches areas with non-trivial risk. Why this tier:
Review process: Full human review — logic, architecture, edge cases. Stats
|
Greptile SummaryAdds a dashboard grid wrapper that displays a measured SVG snap-cell overlay while tiles are dragged or resized.
Confidence Score: 5/5The PR appears safe to merge with no blocking failures remaining. No blocking failures remain. Important Files Changed
Reviews (4): Last reviewed commit: "Track the landing cell and fix the overl..." | Re-trigger Greptile |
E2E Test Results✅ All tests passed • 242 passed • 1 skipped • 992s
Tests ran across 4 shards in parallel. |
Deep Review
✅ No critical issues found. The 🟡 P2 — recommended
🔵 P3 nitpicks (2)
Reviewers (0 of ~8 dispatched): multi-agent fan-out could not run — the sandbox failed to start any shell process, so reviewer sub-agents (correctness, testing, maintainability, performance, project-standards, agent-native, learnings) never executed. Findings above come from a manual read-only pass by the orchestrator applying those lenses directly. Testing gaps: No tests cover |
Fix the failing lint: use a stable key for the snap cells (the array-index key added the one warning that pushed the app over its max-warnings cap) and rename the fade-in keyframe to kebab-case for stylelint. Add the component tests the review asked for: - SnapGridLayout drag/resize lifecycle: overlay mounts on start, focus tracks the moving tile, overlay clears on drop, and each caller callback still fires with its original arguments. - GridSnapOverlay rendering: one rect per cell for the measured size, and the focus neighborhood gets the near class while the rest do not. - A nonzero-containerPadding case for the geometry helper. Maintainability nits: share the default margin/padding via gridSnap, return colWidth from computeSnapCells so the overlay does not recompute it, memoize the drag/resize handlers, and drop the redundant tuple casts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Pushed ff70d23 to address the review. Lint (the red check): the snap cells used an array-index key, which added the one warning that tipped the app package over its P2 (tests): added component tests for both new pieces.
P3 nits: shared the default margin/padding through |
SnapGridLayout now imports FocusRect from gridSnap directly, so the re-export from GridSnapOverlay is dead. Remove it to satisfy knip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@alex-fedotyev Very slick. Potential improvement: Is there a way to detect an invalid location for a tile and shade the boxes as red (or an obvious indicator that the placement wont work). See attached video. |
Addresses review feedback on the snap grid: - The highlighted cells now follow where the tile will actually land (react-grid-layout's compacted placeholder position) instead of the raw cursor cell. Dragging a tile over a gap now shows it settling where vertical compaction will put it, not under the cursor where it won't stay. - The overlay now appears only once a tile actually moves, not on the initial mousedown, so clicking a tile or its controls no longer flashes the grid or leaves it stuck on. A window pointerup/pointercancel safety net also tears it down if react-grid-layout skips its stop callback (e.g. the pointer is released over a menu that opened mid-drag). Updates the SnapGridLayout tests for the new lifecycle: start without a move never activates the overlay, pointer release clears it, and focus tracks the landing rect rather than the cursor. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@teeohhem Good call, and thanks for the video, made the rough edge easy to see. Digging in, there isn't really an "invalid" position to flag in this grid: react-grid-layout clamps a tile to the columns (you can't push it out left or right) and just grows the grid downward, and dragging over other tiles is meant to push them out of the way. So a red "won't work" state would almost never fire, and where it did it'd wrongly imply the move isn't allowed. The real rough edge is the one in your video: when you drag a tile down over empty space, vertical compaction pulls it back up on release, but the highlight was following the cursor, so it looked like it would land somewhere it won't. Fixed that instead:
Pushed in 188cd73, give it another spin. |
Add a snap grid that appears while a dashboard tile is dragged or resized, so it is clear where the tile will land.
Summary
While a tile is being moved or resized, SnapGridLayout draws GridSnapOverlay behind the tiles: it outlines the grid cells the tile can snap to and brightens the cells around the tile's current position. It clears on drop. The overlay uses the same geometry
react-grid-layoutuses to place items, so the guides line up with where a tile actually lands, including the right and bottom edges (a naive line-per-column would sit onemarginshort there).Changes
WidthProvider(ReactGridLayout)that tracks the live drag/resize position and shows the overlay only while a tile is moving.gridSnap.tswith the pure cell/neighbor geometry (computeSnapCells,computeSnapColWidth) plus unit tests.ReactGridLayoutusages inDBDashboardPageforSnapGridLayout. Props are unchanged; the wrapper passes everything through.Why
Dragging a tile on a dense dashboard gives no feedback about the grid it snaps to, so it is easy to misjudge where a tile will land. Outlining the actual snap cells (rather than lines on the column pitch) makes all four edges of the dropped tile land on a visible cell edge, and highlighting only the neighborhood keeps the rest of the grid faint so it does not compete with the tile content. The geometry lives in a pure helper so the alignment and neighbor math are unit tested.
Test plan
eslint+tscon the changed files (clean)gridSnap.test.ts(column width, cell coverage, tile-edge alignment, neighbor detection); existing dashboard suites still passUI checks
ResizeObserver), so it stays aligned at any viewport width.SnapGridLayoutandGridSnapOverlayare grid wiring / overlay internals, not reusable UI components a Storybook story would exercise.What is not in this PR
Screenshots