Skip to content

[drag-engine] Add drag and drop primitives - #5487

Open
flaviendelangle wants to merge 146 commits into
mui:masterfrom
flaviendelangle:drag-engine
Open

flaviendelangle wants to merge 146 commits into
mui:masterfrom
flaviendelangle:drag-engine

Conversation

@flaviendelangle

@flaviendelangle flaviendelangle commented Aug 13, 2026

Copy link
Copy Markdown
Member

Documentation
Feature comparison with dnd kit, React Aria, and Pragmatic drag and drop

Summary

Adds unstyled drag-and-drop components and hooks under the Draggable namespace, with mouse, touch, and pen support:

  • Draggable.Provider supplies a default kind for simple interactions and the React context boundary for custom previews.
  • Draggable.Root creates a drag source. Add Draggable.Handle to limit where a drag starts.
  • Draggable.Target accepts drops and exposes target coordinates and snapping helpers.
  • Draggable.Preview configures the default source clone or renders custom preview content.
  • Draggable.CollisionProvider resolves insertion positions for sorting. Applications control the order and can update it on drop or while dragging.
  • Draggable.Viewport enables auto-scroll for a container or implements custom scrolling.
  • Draggable.useDragMonitor observes drag events, Draggable.useActiveDrag reads the active source, and Draggable.useDragDropManager provides imperative registration and cancellation.

Basic usage

Simple interactions need no explicit kind or payload. Sources and targets share their provider's default kind:

import { Draggable } from '@base-ui/react/draggable';

<Draggable.Provider>
  <Draggable.Root>Drag me</Draggable.Root>
  <Draggable.Target onDraggableDrop={() => console.log('Dropped')}>
    Drop here
  </Draggable.Target>
</Draggable.Provider>;

For typed data, share a kind between the source and target. Drop handlers infer source.payload from accept:

const card = Draggable.createKind<Card>('card');

<Draggable.Provider>
  <Draggable.Root kind={card} payload={cardData}>
    {cardData.title}
  </Draggable.Root>
  <Draggable.Target
    accept={card}
    onDraggableDrop={({ source }) => move(source.payload.id)}
  >
    Done
  </Draggable.Target>
</Draggable.Provider>;

Use getPayload to derive data at pickup. Explicit shared kinds also allow interactions across providers; the drag manager remains page-wide.

Activation thresholds, movement modifiers, data attributes, and CSS variables control drag behavior and styling. Auto-scroll is opt-in for each container through Draggable.Viewport or imperative registration, including separate registration for page scrolling.

Dragging is pointer-driven. Applications provide equivalent keyboard and click or tap actions through move menus, buttons, or shortcuts. The documentation includes accessibility guidance and sorting examples with keyboard shortcuts.

@flaviendelangle flaviendelangle self-assigned this Aug 13, 2026
@flaviendelangle flaviendelangle added type: new feature Expand the scope of the product to solve a new problem. scope: all components Widespread work has an impact on almost all components. labels Aug 13, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 13, 2026

Copy link
Copy Markdown

commit: 51aa639

@netlify

netlify Bot commented Aug 13, 2026

Copy link
Copy Markdown

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 51aa639
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/6ab299866f7582000831fddf
😎 Deploy Preview https://deploy-preview-5487--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@code-infra-dashboard

code-infra-dashboard Bot commented Aug 13, 2026

Copy link
Copy Markdown

Bundle size

Bundle Parsed size Gzip size
@base-ui/react 🔺+87.1KB(+19.09%) 🔺+28.5KB(+19.14%)

Details of bundle changes

Performance

Total duration: 1,350.11 ms +38.65 ms(+2.9%) | Renders: 76 (+0) | Paint: 2,261.56 ms +68.02 ms(+3.1%)

Test Duration Renders
Dialog mount (300 instances) 35.91 ms 🔺+8.43 ms(+30.7%) 1 (+0)

14 tests within noise — details

Metric alarms

Test Metric Change
Dialog mount (300 instances) bench:paint 🔺 +15.02 ms

Check out the code infra dashboard for more information about this PR.

@flaviendelangle

Copy link
Copy Markdown
Member Author

CI follow-up: the repo-wide llms-full.txt generation memory fix has been extracted to #5488. The equivalent patch remains on this branch temporarily so this PR can validate cleanly; it will fall out of the diff once #5488 lands.

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Sep 21, 2026
@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Sep 21, 2026
flaviendelangle and others added 14 commits September 21, 2026 16:32
Restructure the Draggable page to match the other Base UI pages: usage
guidelines, anatomy, concept sections (kinds and payloads, drag events,
drop targets, auto-scrolling, testing), examples, then the API reference.
Rewrite the prose without engine jargon and tighten the JSDoc that feeds
the reference tables.

Replace the dashboard demos' move form with an Alt+Arrow shortcut, drop
demos that duplicate the page hero, style the example forms, and use
primitive or memoized payloads everywhere. Move the five large examples
to the drag-engine experiments with their tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Rebuild the draggable tabs experiment on the workspace UI of the former
docs example, keeping its four variants, and drop the duplicate tabs,
free dragging, and week scheduler experiments whose features the figma
board and calendar already cover. Name the two kanban experiments after
their drop feedback: placeholder card versus line indicator.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Merge the content components into the default exports, inline the
scrolling board's viewport, shorten the canvas camera update, drop
trackDragOver from the axis demo, and share one ref-callback helper in
the manager demo. Add focus markers so each collapsed code block opens
on the lines the demo is about instead of the imports.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Global keys are shared by the page, so the docs ask callers to prefix
them, but the function no longer throws: collision risk is the caller's
responsibility.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: all components Widespread work has an impact on almost all components. type: new feature Expand the scope of the product to solve a new problem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants