Skip to content

ENG-3398: Fix column reorder drop target in Datamap report modal#7905

Merged
gilluminate merged 3 commits intomainfrom
gill/ENG-3398/datamap-column-reorder-revert
Apr 14, 2026
Merged

ENG-3398: Fix column reorder drop target in Datamap report modal#7905
gilluminate merged 3 commits intomainfrom
gill/ENG-3398/datamap-column-reorder-revert

Conversation

@gilluminate
Copy link
Copy Markdown
Contributor

@gilluminate gilluminate commented Apr 13, 2026

Ticket ENG-3398

Description Of Changes

In the Datamap report's "Edit columns" modal, dragging a column to a new position appeared to revert before succeeding when the drop released slightly off the drag-handle icon. Root cause: drag(drop(ref)) in DraggableColumnListItem applied both the drag source and drop target to the same ref on the 20px drag-handle <div>. Hover and drop only fired inside the handle's bounding box, so any release a few pixels to the side fell outside the drop target and the HTML5 backend cancelled the drop, snapping the native drag ghost back to its origin.

Fix: split the single ref into two:

  • rowRef — drop target + drag preview on the full row <Flex> (hover fires anywhere on the row)
  • dragRef — drag source on the handle icon (preserves the grab-handle UX)

With the drop target now covering the whole row, drops register at the cursor wherever the user releases, the native ghost lands cleanly, and the reorder completes without the visual revert.

Code Changes

  • clients/admin-ui/src/features/common/table/column-settings/DraggableColumnListItem.tsx: split ref into rowRef (drop target + preview) and dragRef (drag source); update hover handler to measure against rowRef.

Steps to Confirm

  1. Navigate to the Datamap report page.
  2. Open the more menu → "Edit columns".
  3. Drag a column up or down and release anywhere along the row (not just on the drag-handle icon).
  4. Confirm the column lands in the new position without any visual revert/snap-back.
  5. Click Save and confirm the new order is applied to the table headers.
  6. Reload and confirm the order persists.

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • Ensure that your downrev is up to date with the latest revision on main
    • Ensure that your downgrade() migration is correct and works
      • If a downgrade migration is not possible for this change, please call this out in the PR description!
    • No migrations
  • Documentation:
    • Documentation complete, PR opened in fidesdocs
    • Documentation issue created in fidesdocs
    • If there are any new client scopes created as part of the pull request, remember to update public-facing documentation that references our scope registry
    • No documentation updates required

gilluminate and others added 2 commits April 13, 2026 12:04
Split the single ref used by react-dnd so the drop target covers the
whole row (not just the 20px drag handle). Hover and drop now register
anywhere on the row, eliminating the visual "revert" users saw when
releasing slightly off the handle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Apr 14, 2026 8:28pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Apr 14, 2026 8:28pm

Request Review

@gilluminate gilluminate marked this pull request as ready for review April 13, 2026 18:05
@gilluminate gilluminate requested a review from a team as a code owner April 13, 2026 18:05
@gilluminate gilluminate requested review from lucanovera and removed request for a team April 13, 2026 18:05
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: Fix column reorder drop target in Datamap report modal

Verdict: Good to merge with one minor optional cleanup noted inline.

What the PR does

Splits the single ref (which was simultaneously drag source and drop target) into two separate refs:

  • rowRef — attached to the full <Flex> row, used as the drop target and drag preview anchor
  • dragRef — attached to the handle icon <div> only, used as the drag source

This correctly fixes the root cause: the HTML5 DnD backend was registering drops only within the 20px handle icon bounding box instead of anywhere on the row. The split-ref pattern is the standard react-dnd solution for this class of bug.

What's correct

  • drop(rowRef) + drag(dragRef) + preview(rowRef) is the right call order; preview is correctly moved from JSX-level to inside the hook body and removed from the hook's return value.
  • data-handler-id={handlerId} stays on the <Flex> (the drop target element), which is required for react-dnd's DOM correlation.
  • The comment explaining the two refs (// rowRef is the drop target...) explains why, which is exactly what makes this maintainable.
  • Blast radius is limited to this component and its single consumer (DraggableColumnList.tsx).

Suggestions

Inline (line 59): The ?. optional chain on rowRef.current is redundant after the null guard — see inline comment for the one-character fix. Pre-existing, but touched directly by this PR.

Follow-up (no action needed for merge):

  • There are no test files for this component. A drag-and-drop integration test (e.g., Playwright or @testing-library/user-event) would prevent this class of regression from silently reappearing.
  • The two inline style props (opacity, cursor) are pre-existing candidates for Tailwind utility classes (opacity-20, cursor-grab/cursor-grabbing), but that's a separate cleanup.

🔬 Codegraph: connected (46363 nodes)


💡 Write /code-review in a comment to re-run this review.

}

const hoverBoundingRect = ref.current?.getBoundingClientRect();
const hoverBoundingRect = rowRef.current?.getBoundingClientRect();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clients/admin-ui/src/features/common/table/column-settings/DraggableColumnListItem.tsx:59

The optional chaining (?.) here is redundant — rowRef.current is already guaranteed non-null by the if (!rowRef.current) { return; } guard on the line above this hunk. As written, hoverBoundingRect infers as DOMRect | undefined, even though it can never actually be undefined at runtime. It's a one-character fix:

const hoverBoundingRect = rowRef.current.getBoundingClientRect();

This is pre-existing, but the PR renames refrowRef on this exact line, so it's the natural moment to clean it up.

@github-actions
Copy link
Copy Markdown

Title Lines Statements Branches Functions
admin-ui Coverage: 7%
5.89% (2561/43445) 4.93% (1214/24589) 3.98% (512/12862)
fides-js Coverage: 78%
78.98% (1962/2484) 65.55% (1214/1852) 72.57% (336/463)
privacy-center Coverage: 88%
85.93% (330/384) 81.1% (176/217) 78.87% (56/71)

Copy link
Copy Markdown
Contributor

@lucanovera lucanovera left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed the original behavior on nightly and compared it to the fix in this branch. Nice improvement, the reorder is way easier with the new larger target. Approved 💯

@gilluminate gilluminate added this pull request to the merge queue Apr 14, 2026
Merged via the queue into main with commit b9966e9 Apr 14, 2026
51 checks passed
@gilluminate gilluminate deleted the gill/ENG-3398/datamap-column-reorder-revert branch April 14, 2026 20:40
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.

2 participants