Skip to content

Commit dd5d666

Browse files
travor20814claude
andcommitted
fix(react/table): pass dragHandleProps to Skeleton when loading in drag mode
When loading is true during a refetch with existing data, rows remain wrapped in Draggable but the drag handle cell renders a Skeleton without the required data-rfd-drag-handle-* attributes, causing dnd to lose the handle reference. Spread dragHandleProps onto Skeleton in drag mode. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent fd3412f commit dd5d666

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

packages/react/src/Table/Table.stories.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,54 @@ export const DraggableRows: Story = {
14181418
},
14191419
};
14201420

1421+
export const DraggableRowsWithRefetch: Story = {
1422+
render: function DraggableRowsWithRefetchStory() {
1423+
const [data, setData] = useState<DataType[]>(baseData);
1424+
const [loading, setLoading] = useState(false);
1425+
1426+
const draggable: TableDraggable<DataType> = useMemo(
1427+
() => ({
1428+
enabled: true,
1429+
onDragEnd: (newData: DataType[]) => setData(newData),
1430+
}),
1431+
[],
1432+
);
1433+
1434+
const scroll = useMemo(() => ({ y: 300 }), []);
1435+
1436+
const handleRefetch = useCallback(() => {
1437+
setLoading(true);
1438+
setTimeout(() => {
1439+
setLoading(false);
1440+
}, 1500);
1441+
}, []);
1442+
1443+
return (
1444+
<div>
1445+
<p style={{ margin: '0 0 8px' }}>
1446+
Simulates a refetch while data rows are still rendered inside
1447+
Draggable. Click the button to trigger loading — drag handles should
1448+
remain functional without dnd errors.
1449+
</p>
1450+
<Button
1451+
style={{ marginBottom: '16px' }}
1452+
onClick={handleRefetch}
1453+
variant="base-primary"
1454+
>
1455+
Simulate Refetch
1456+
</Button>
1457+
<Table<DataType>
1458+
columns={baseColumns}
1459+
dataSource={data}
1460+
draggable={draggable}
1461+
loading={loading}
1462+
scroll={scroll}
1463+
/>
1464+
</div>
1465+
);
1466+
},
1467+
};
1468+
14211469
export const PinnableRows: Story = {
14221470
render: function PinnableRowsStory() {
14231471
const [pinnedRowKeys, setPinnedRowKeys] = useState<string[]>([]);

packages/react/src/Table/components/TableDragOrPinHandleCell.spec.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,5 +301,29 @@ describe('<TableDragOrPinHandleCell />', () => {
301301

302302
expect(skeleton).toBeInTheDocument();
303303
});
304+
305+
it('should pass dragHandleProps to skeleton in drag mode when loading', () => {
306+
const dragHandleProps = { 'data-testid': 'drag-handle-skeleton' };
307+
308+
renderWithContext(
309+
{ dragHandleProps, mode: 'drag', record: testRecord },
310+
{ ...defaultContextValue, loading: true },
311+
);
312+
313+
expect(screen.getByTestId('drag-handle-skeleton')).toBeInTheDocument();
314+
});
315+
316+
it('should not pass dragHandleProps to skeleton in pin mode when loading', () => {
317+
const dragHandleProps = { 'data-testid': 'drag-handle-skeleton' };
318+
319+
renderWithContext(
320+
{ dragHandleProps, mode: 'pin', record: testRecord },
321+
{ ...defaultContextValue, loading: true },
322+
);
323+
324+
expect(
325+
screen.queryByTestId('drag-handle-skeleton'),
326+
).not.toBeInTheDocument();
327+
});
304328
});
305329
});

packages/react/src/Table/components/TableDragOrPinHandleCell.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,13 @@ function TableDragOrPinHandleCellInner<
8585
}
8686

8787
if (loading) {
88-
return <Skeleton variant="body-highlight" width="100%" />;
88+
return (
89+
<Skeleton
90+
variant="body-highlight"
91+
width="100%"
92+
{...(mode === 'drag' ? dragHandleProps : {})}
93+
/>
94+
);
8995
}
9096

9197
if (mode === 'drag') {

0 commit comments

Comments
 (0)