Skip to content

fix(kanban): move drag-and-drop placeholder inside innerRef container#18939

Open
hnshah wants to merge 1 commit intotwentyhq:mainfrom
hnshah:fix/kanban-drag-drop-placeholder
Open

fix(kanban): move drag-and-drop placeholder inside innerRef container#18939
hnshah wants to merge 1 commit intotwentyhq:mainfrom
hnshah:fix/kanban-drag-drop-placeholder

Conversation

@hnshah
Copy link
Copy Markdown

@hnshah hnshah commented Mar 25, 2026

fix(kanban): move drag-and-drop placeholder inside innerRef container

Fixes #18842

The Kanban drag-and-drop was only registering drops near the top of columns because the @hello-pangea/dnd placeholder was rendered outside the innerRef container, breaking the library's droppable area measurement.

Root Cause

The library requires droppableProvided.placeholder to be a direct child of the element that receives droppableProvided.innerRef.

Before (broken):

  • innerRef was on StyledColumnCardsContainer (inside memo boundary)
  • placeholder was in parent StyledColumn (outside memo boundary)
  • Result: Library measured wrong droppable area, drops only worked at top

After (fixed):

  • innerRef moved to StyledColumn (outside memo boundary)
  • placeholder stays in StyledColumn (same parent as innerRef)
  • Result: Both inside same DOM element, library measures correctly

Changes

RecordBoardColumn.tsx:

  • Added ref={droppableProvided.innerRef} to StyledColumn
  • Added {...droppableProvided.droppableProps} to StyledColumn
  • Removed droppableProvided from RecordBoardColumnCardsContainer props

RecordBoardColumnCardsContainer.tsx:

  • Removed droppableProvided from component props and type
  • Removed ref and {...droppableProps} from StyledColumnCardsContainer
  • Removed unused DroppableProvided import

Why This Works

The DragAndDropLibraryLegacyReRenderBreaker (React.memo wrapper) blocks re-renders of the card list during drag — this is the performance optimization from PR #15714.

By lifting innerRef to the parent StyledColumn, both the memo'd cards and the placeholder live inside the innerRef DOM element, satisfying the library's requirements while preserving the performance optimization.

Testing

Tested manually with 15+ card columns:

  • ✅ Drag to top of column: works
  • ✅ Drag to middle of column: works (was failing)
  • ✅ Drag to bottom of column: works (was failing)
  • ✅ Long columns with scroll: works

History

Credit

Root cause analysis by @SONARly (#18842 (comment))

Fixes twentyhq#18842

The Kanban drag-and-drop was only registering drops near the top of columns because the @hello-pangea/dnd placeholder was rendered outside the innerRef container, breaking the library's droppable area measurement.

## Root Cause

The library requires `droppableProvided.placeholder` to be a direct child of the element that receives `droppableProvided.innerRef`.

**Before (broken):**
- `innerRef` was on `StyledColumnCardsContainer` (inside memo boundary)
- `placeholder` was in parent `StyledColumn` (outside memo boundary)
- Result: Library measured wrong droppable area, drops only worked at top

**After (fixed):**
- `innerRef` moved to `StyledColumn` (outside memo boundary)
- `placeholder` stays in `StyledColumn` (same parent as innerRef)
- Result: Both inside same DOM element, library measures correctly

## Changes

**RecordBoardColumn.tsx:**
- Added `ref={droppableProvided.innerRef}` to `StyledColumn`
- Added `{...droppableProvided.droppableProps}` to `StyledColumn`
- Removed `droppableProvided` from `RecordBoardColumnCardsContainer` props

**RecordBoardColumnCardsContainer.tsx:**
- Removed `droppableProvided` from component props and type
- Removed `ref` and `{...droppableProps}` from `StyledColumnCardsContainer`
- Removed unused `DroppableProvided` import

## Why This Works

The `DragAndDropLibraryLegacyReRenderBreaker` (React.memo wrapper) blocks re-renders of the card list during drag — this is the performance optimization from PR twentyhq#15714.

By lifting `innerRef` to the parent `StyledColumn`, both the memo'd cards and the placeholder live inside the innerRef DOM element, satisfying the library's requirements while preserving the performance optimization.

## Testing

Tested manually with 15+ card columns:
- ✅ Drag to top of column: works
- ✅ Drag to middle of column: works (was failing)
- ✅ Drag to bottom of column: works (was failing)
- ✅ Long columns with scroll: works

## History

- **PR twentyhq#7600** (Oct 2024): Originally fixed by placing placeholder inside innerRef
- **PR twentyhq#15714** (Nov 2025): Performance optimization moved placeholder outside, breaking the fix
- **This PR**: Restores correct placeholder placement while keeping performance optimization

## Credit

Root cause analysis by @SONARly (twentyhq#18842 (comment))
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@github-actions
Copy link
Copy Markdown
Contributor

Welcome!

Hello there, congrats on your first PR! We're excited to have you contributing to this project.
By submitting your Pull Request, you acknowledge that you agree with the terms of our Contributor License Agreement.

Generated by 🚫 dangerJS against 29a5a0a

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files


Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

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.

Kanban drag-and-drop only registers drops near the top of a column

1 participant