fix: move droppable placeholder back inside innerRef container in Kanban board
https://sonarly.com/issue/17390?type=bug Kanban board drops only register near the top of target columns because the `@hello-pangea/dnd` placeholder was moved outside the `innerRef` container, breaking the library's droppable area measurement. Fix: **What changed:** Moved `droppableProvided.innerRef` and `droppableProvided.droppableProps` from `StyledColumnCardsContainer` (inside the memo boundary) up to `StyledColumn` in `RecordBoardColumn.tsx` (outside the memo boundary). This ensures both the card list and the placeholder are children of the `innerRef` element, which is required by `@hello-pangea/dnd` for correct droppable area measurement. **RecordBoardColumn.tsx:** - Added `ref={droppableProvided.innerRef}` and `{...droppableProvided.droppableProps}` to `StyledColumn` - Removed `droppableProvided` from props passed to `RecordBoardColumnCardsContainer` **RecordBoardColumnCardsContainer.tsx:** - Removed `droppableProvided` from component props and type definition - Removed `ref` and spread of `droppableProps` from `StyledColumnCardsContainer` - Removed unused `DroppableProvided` type 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. Previously, to work around this, the placeholder was placed outside the `innerRef` container, breaking drop zone detection. 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.
This commit is contained in:
+5
-2
@@ -65,12 +65,15 @@ export const RecordBoardColumn = ({
|
||||
>
|
||||
<Droppable droppableId={recordBoardColumnId}>
|
||||
{(droppableProvided) => (
|
||||
<StyledColumn>
|
||||
<StyledColumn
|
||||
ref={droppableProvided.innerRef}
|
||||
// oxlint-disable-next-line react/jsx-props-no-spreading
|
||||
{...droppableProvided.droppableProps}
|
||||
>
|
||||
<DragAndDropLibraryLegacyReRenderBreaker
|
||||
memoizationId={recordBoardColumnId}
|
||||
>
|
||||
<RecordBoardColumnCardsContainer
|
||||
droppableProvided={droppableProvided}
|
||||
recordBoardColumnId={recordBoardColumnId}
|
||||
/>
|
||||
</DragAndDropLibraryLegacyReRenderBreaker>
|
||||
|
||||
+2
-8
@@ -1,5 +1,5 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { Draggable, type DroppableProvided } from '@hello-pangea/dnd';
|
||||
import { Draggable } from '@hello-pangea/dnd';
|
||||
import { useContext } from 'react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
@@ -25,12 +25,10 @@ const StyledNewButtonContainer = styled.div`
|
||||
|
||||
type RecordBoardColumnCardsContainerProps = {
|
||||
recordBoardColumnId: string;
|
||||
droppableProvided: DroppableProvided;
|
||||
};
|
||||
|
||||
export const RecordBoardColumnCardsContainer = ({
|
||||
recordBoardColumnId,
|
||||
droppableProvided,
|
||||
}: RecordBoardColumnCardsContainerProps) => {
|
||||
const { columnDefinition } = useContext(RecordBoardColumnContext);
|
||||
|
||||
@@ -45,11 +43,7 @@ export const RecordBoardColumnCardsContainer = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledColumnCardsContainer
|
||||
ref={droppableProvided?.innerRef}
|
||||
// oxlint-disable-next-line react/jsx-props-no-spreading
|
||||
{...droppableProvided?.droppableProps}
|
||||
>
|
||||
<StyledColumnCardsContainer>
|
||||
{recordIndexRecordIdsByGroup.map((recordId, index) => (
|
||||
<RecordBoardCardDraggableContainer
|
||||
key={recordId}
|
||||
|
||||
Reference in New Issue
Block a user