React DnD TreeView

A headless React treeview component with built-in drag-and-drop reordering for touch and pointer devices.

Library
npm
v3.5.4
607stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
51/100Fair
Development Activity12
Maintenance44
Community60
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture78
Code Quality68
Innovation60
Learning Curve55

@minoru/react-dnd-treeview renders arbitrary hierarchical data as a draggable, droppable list on top of react-dnd, while leaving all node markup to the consumer through a render-prop API. It ships a MultiBackend configuration that combines the HTML5 and touch backends out of the box, so the same tree works with mouse, trackpad, and touch input without separate code paths.

Beyond basic re-parenting, the library exposes index-aware drop utilities for manual sort ordering, an imperative ref API to open/close nodes programmatically, and support for accepting drops from outside its own drag type (including native file drops). It stays unopinionated about styling and DOM structure, making it a building block for file explorers, nested outliners, and admin category/menu editors rather than a themed, ready-to-use widget.

What You Get

  • A Tree component plus re-exported MultiBackend/DndProvider so no separate react-dnd backend wiring is required beyond calling getBackendOptions()
  • Tree-mutation utilities (mutateTree, mutateTreeWithIndex, getDescendants, isAncestor, getParents) for updating the flat node array after a drop
  • An imperative TreeMethods ref API (open, close, openAll, closeAll) for controlling expand/collapse state from outside the component
  • Full TypeScript types for nodes, render params, drop options, and classes, generic over a user-defined data payload type
  • A large Storybook example suite covering directory structures, multi-select, editable nodes, external drops, and animated expand/collapse

Common Use Cases

  • File and folder explorer UIs with drag-to-move between directories
  • Nested outline or task-list tools where items are reordered and re-nested by hand
  • Admin panel category, navigation-menu, or taxonomy trees edited via drag-and-drop
  • Hierarchical record editors (org charts, bill-of-materials trees) that persist re-parenting to a backend

Under The Hood

Architecture Tree.tsx forwards a ref through a Providers composition (TreeProvider, DragControlProvider, PlaceholderProvider) that supplies React context consumed via hooks (useTreeContext, useDropRoot, useDragNode, useDropNode) by Container and Node, which recursively render each other to reproduce the tree’s nesting rather than flattening it into a single list. TreeProvider centralizes the two effectful concerns of the library: open/closed id state (useOpenIdsHelper) and computing the mutated node array on drop (mutateTree/mutateTreeWithIndex), then hands the result back to the consumer via onDrop instead of owning the tree data itself, keeping the library controlled with respect to state. Drag/drop mechanics are delegated to react-dnd (useDrag/useDrop wrapped in useDragNode/useDropNode/useDropRoot), including a manual DOM-traversal check in useDragNode’s register() to disambiguate which nested list item actually initiated a touch-originated drag.

Tech Stack A TypeScript library targeting React 18/19 as peer dependencies, built with Rollup (rollup-plugin-typescript2, rollup-plugin-peer-deps-external) into a single ESM bundle with generated .d.ts files. Drag-and-drop comes from react-dnd 16.x combined with react-dnd-html5-backend and react-dnd-touch-backend via dnd-multi-backend, so pointer and touch input are both handled through one MultiBackend. Animated expand/collapse uses framer-motion, with @juggle/resize-observer and react-use-measure handling cross-browser height measurement. Storybook 10 with @storybook/addon-vitest and a Playwright-driven browser project hosts the example/demo suite that doubles as documentation, while Biome 2.x replaces ESLint/Prettier for linting and formatting and Vitest runs the unit project.

Code Quality Thirteen test files exist, one per pure utility module (compareItems, getDescendants, getDestIndex, getModifiedIndex, getParents, getTreeItem, hasChildNodes, isAncestor, isDroppable, isNodeModel, mutateTree, mutateTreeWithIndex, getBackendOptions), giving thorough coverage of the tree-math layer, but there is no dedicated unit test file for the interactive React components or hooks themselves (Tree, Container, Node, useDragNode, useDropNode) — that behavior is only exercised indirectly through Storybook interaction stories. TypeScript is used throughout with exported types for every public shape, and generics thread a user-defined payload type through the whole API. A single release workflow runs the test suite before publishing, but there is no separate PR-gating CI check.

API Design The public surface is small and consistent: one Tree component driven by a render prop, a handful of typed callback props (onDrop, canDrop, canDrag, onChangeOpen), and a small set of exported utilities and types. Getting started requires wiring a DndProvider with MultiBackend/getBackendOptions() and supplying a render function, which is a modest amount of boilerplate compared to a themed drop-in widget, but it buys full control over markup with no CSS to override. Prop and type naming is consistent across the library (NodeModel, DropOptions, TreeProps, TreeMethods), and the README documents the full component API and node-property table in one place.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search