dnd-kit icon indicating copy to clipboard operation
dnd-kit copied to clipboard

[Experimental] Introduce `useDragHandle` hook

Open clauderic opened this issue 7 months ago • 2 comments

This PR introduces a useDragHandle hook that allows React consumers to set a drag handle in a different location than where useDraggable or useSortable is used.

Resolves https://github.com/clauderic/dnd-kit/issues/1738

Example usage — two separate components

Below the draggable is declared in a row component, while the dedicated handle lives in a different component.

import {DragDropProvider} from '@dnd-kit/react';
import {useSortable} from '@dnd-kit/react/sortable';
import {useDragHandle} from '@dnd-kit/react';

import {
  ColumnDef,
  Row,
  flexRender,
  useReactTable,
  getCoreRowModel,
} from '@tanstack/react-table';

// ─────────────────────────────────────────────────────
// Cell renderer — only cares about being the drag handle
// ─────────────────────────────────────────────────────
function DragCell({rowId}: {rowId: string}) {
  const handleRef = useDragHandle({id: rowId});   // same id as the row
  return (
    <button ref={handleRef} aria-label="Drag row" style={{cursor: 'grab'}}>
      ⠿
    </button>
  );
}

// ─────────────────────────────────────────────────────
// Draggable row — owns the sortable behaviour
// ─────────────────────────────────────────────────────
function DraggableRow({row}: {row: Row<Person>}) {
  const {ref} = useSortable({id: row.id, index: row.index});        // row itself is sortable
  return (
    <tr ref={ref}>
      {row.getVisibleCells().map((cell) => (
        <td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
      ))}
    </tr>
  );
}

// ─────────────────────────────────────────────────────
// Table setup (irrelevant plumbing omitted for clarity)
// ─────────────────────────────────────────────────────
function App() {
  const columns = React.useMemo<ColumnDef<Person>[]>(() => [
    {                                             // dedicated “move” column
      id: 'drag',
      header: '↕︎',
      size: 40,
      cell: ({row}) => <DragCell rowId={row.id} />, // ← handle rendered here
    },
    // …other columns…
  ], []);

  const table = useReactTable({
    data, columns, getCoreRowModel: getCoreRowModel(), getRowId: r => r.id,
  });

  return (
    <DragDropProvider>
      <table>
        <tbody>
          {table.getRowModel().rows.map((row) => (
            <DraggableRow key={row.id} row={row} />
          ))}
        </tbody>
      </table>
    </DragDropProvider>
  );
}

The key takeaway: useDragHandle does not need to live in the same component where useDraggable/useSortable is invoked—perfect for table rows, list items with nested actions, or any layout where the “grab-area” is rendered deeper in the tree.

clauderic avatar Jun 12 '25 14:06 clauderic

⚠️ No Changeset found

Latest commit: 5b9017664ef9a0b6684823940b32bf57b13f6349

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

changeset-bot[bot] avatar Jun 12 '25 14:06 changeset-bot[bot]

Open in StackBlitz

@dnd-kit/abstract

npm i https://pkg.pr.new/clauderic/dnd-kit/@dnd-kit/abstract@1740
@dnd-kit/collision

npm i https://pkg.pr.new/clauderic/dnd-kit/@dnd-kit/collision@1740
@dnd-kit/dom

npm i https://pkg.pr.new/clauderic/dnd-kit/@dnd-kit/dom@1740
@dnd-kit/geometry

npm i https://pkg.pr.new/clauderic/dnd-kit/@dnd-kit/geometry@1740
@dnd-kit/helpers

npm i https://pkg.pr.new/clauderic/dnd-kit/@dnd-kit/helpers@1740
@dnd-kit/react

npm i https://pkg.pr.new/clauderic/dnd-kit/@dnd-kit/react@1740
@dnd-kit/state

npm i https://pkg.pr.new/clauderic/dnd-kit/@dnd-kit/state@1740

commit: 5b90176

pkg-pr-new[bot] avatar Jun 12 '25 14:06 pkg-pr-new[bot]