Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new drag-and-drop engine #598

Open
wants to merge 110 commits into
base: main
Choose a base branch
from
Open

Implement new drag-and-drop engine #598

wants to merge 110 commits into from

Conversation

chrisvxd
Copy link
Member

@chrisvxd chrisvxd commented Sep 4, 2024

Implement a new drag-and-drop engine using the experimental dnd-kit release. This is a backwards compatible upgrade, focused on two new pieces of functionality:

  1. Dragging between nested areas (closes Support dragging between DropZone areas #123)
  2. Dragging across advanced CSS layouts (inline, grid, flexbox) via elimination of edit wrappers (Explore elimination of edit wrappers #455, Feature request: DropZones support horizontal direction #520)
Kapture_2024-11-23_at_17.36.04.mp4

This implementation includes additional periphery features:

  • reduce DropZone to height of items unless empty
  • control empty DropZone height with minEmptyHeight prop
  • add DropZone collisionAxis API for forcing collision direction
  • support inline Drawers, deprecating unnecessary props

Closes #556, closes #481, closes #123, closes #455, closes #520, closes #718

Testing

Quick start

Testing guide

  • Report issues in the PR comments
  • Check list of known issues before reporting
  • React strict mode currently causes the drag-and-drop to be unresponsive - if you used create-puck-app, you likely have this enabled in your next.config.js and will need to disable it.
  • Safari still has a bunch of issues
  • Mobile/touch still needs implementing
  • When using canary builds, you must explicitly reference the specific version in your package.json, i.e. "@measured/puck": "0.17.0-canary.XXXXXX"

What to test

  1. The new multi-column layout behaviour
  2. Dragging between DropZones
  3. General Puck functionality
  4. Code reviews welcome

Known issues

  • Latest canary triggers Invalid instance type error on DragDropRegistry.register
  • DragDropContext re-renders on pointer move
  • Overlay appearing inconsistently on hover
  • Doesn't work with React strict mode
  • Overlay not accounting for scroll when iframe disabled
  • Ghosting of item on drop due to rendering before position synced.
  • Zoom changes don't refresh overlays
  • Safari behaviour buggy on desktop and mobile
    • NestedDroppablePlugin not always activating
    • Extra weird ghosting on drop
    • Jittery natural scrolling when dragging, likely due to conflict with AutoScroller
    • Drop position slightly off on drop (requires upstream fix)
  • Drawer items missing grab handler
  • Puckception possible in demo
  • Touch dragging (mobile) not yet fully implemented
  • Dynamic collision mode sometimes locked to y-axis on iOS when zoomed to larger device
  • NestedDroppable plugin occasionally fails to register correct zone on drag start, causing freeze
  • Ghosting on drop
  • Flickering of overlay when hovering over action bar, when action bar is over the item (i.e. when pushed down from top). Only occurs when item is hovered, not selected. To reproduce, remove header in demo, hover over action bar of first item.
  • Preview border truncated on mobile
  • ActionBar can overflow on right of frame, noticeable with inline display modes on smaller viewports (like mobile)
  • Sporadic error when dragging NotFoundError: Failed to execute 'setPointerCapture' on 'Element': No active pointer with the given id is found. (requires upstream fix)
  • Item sometimes sticks to cursor during rapid insertion of new components. Race condition, and highly device dependant. Due to pointerup event not being listened to on document change
  • Active zone not bubbling up when child zone disallows the currently dragged item
  • Overlay position broken when scrolling in custom interfaces
  • Items not selectable in docs
  • Overlay doesn't resize if parent drop zone resizes
  • dnd.disableAutoScroll behaviour ignored
  • NestedDroppablePlugin not correctly setting zones in some scenarios, resulting in unresponsive DropZones. This is likely due to bugs in the debouncing logic. Requires rewrite.
  • Slow drop rendering in some codebases (per this comment)
  • Scroll position not properly accounted for. To reproduce, scroll so second card grid is just in frame, then drag item above. Notice it will snap to above Stats. Possible fallback collision bug.
    • Item also sometimes freezes on drag in this scenario - possible issue with NestedDroppableComponent
  • Auto scroll does not work properly (inconsistent error) - unable to reproduce, but suspect due to nested scroll containers (iframe inside scroll container?)
  • DropZone animates when docs load
  • DropZone minEmptyHeight prop default doesn't match docs
  • DropZone docs missing dragRef (which should also be renamed to ref to make more generic)

Low priority issues

  • Items slightly incorrect when repositioning after dragging between nested areas (requires upstream fix)

Feedback

  • Changing droppable areas feels slow - either reduce debounce or make configurable, or both
  • It's difficult to select the parent item, especially in custom interfaces - consider a "select parent" action in the action bar
  • If the DropZone is full and has no padding, you can't drag it - it just selects the parent item. Difficult to solve for. Might be easier with drag-and-drop in outline in Improve Outline UI #730

Implementation details

  • Use of the experimental dnd-kit release, with upstream contributions, particularly around iframes.
  • A custom dnd-kit plugin called NestedDroppablePlugin for detecting the appropriate droppable when using nested layouts.
  • A custom collision algorithm for complex layouts, inspired by react-beautiful-dnd.
  • Complete rebuild of DropZone and DraggableComponent components.
  • Fully backwards compatible.

Implementation tasks

  • Rebuild DropZone / DraggableComponent
  • Custom collision algorithm
  • Replace active DropZone detection logic with plugin
  • Fix NestedDroppablePlugin on Safari
  • Rebase
  • Don't select chrome UI text when dragging with iframe disabled
  • Fix outline items
  • Tidy implementation
  • Make preview more robust
  • Split different bugfixes
  • Optimise NestedDroppablePlugin
    • Consider using elementFromPoint
      • Need to account for frame enlargement
      • Is this actually more performance
    • Don't resize on each pointer move
  • Update pathData when dragging between areas
  • Add iframe support to dndkit
  • Fix autoscroller
  • Fix drop animation on Safari
  • Prevent action bar from getting cut-off on left side of frame
  • Update .drag permission behaviour
  • Fix undo/redo hotkeys when focus inside iframe
  • Fix ghosting when moving quickly between zones
  • Prevent overlay from flashing in bottom left during drop
  • Review draggable / droppable data attributes, and make types strict
  • Split different features and document
  • Fix build
  • Overlay not showing consistently in docs
  • Fix overlay performance issues in prod build
  • Sporadic flashing of overlay on drop

Bonus

  • Cancel drag if escape key used
  • Add drag handle to overlay item
  • Account for scrolling during drop animation
  • Persist droppable size when dragging between zones
  • Animate droppable resize
  • Retain original drawer item when dragging
  • Add feature flag for full backwards compatibility (perhaps disable by default)

Follow-ons

  • Isolate styles to host
  • Migrate array fields to dndkit
  • Keyboard dragging

Copy link

vercel bot commented Sep 4, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
puck-demo ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 16, 2024 10:04pm
puck-docs ✅ Ready (Inspect) Visit Preview Dec 16, 2024 10:04pm

chrisvxd added a commit that referenced this pull request Sep 7, 2024
This will result in duplicate history entries if the item has a resolveData method. This is difficult to prevent without a deferredDispatch method, similar to that being explored in #598.
chrisvxd added a commit that referenced this pull request Sep 7, 2024
This will result in duplicate history entries if the item has a resolveData method. This is difficult to prevent without a deferredDispatch method, similar to that being explored in #598.
chrisvxd added a commit that referenced this pull request Sep 7, 2024
This will result in duplicate history entries if the item has a resolveData method. This is difficult to prevent without a deferredDispatch method, similar to that being explored in #598.
chrisvxd added a commit that referenced this pull request Sep 9, 2024
This will result in duplicate history entries if the item has a resolveData method. This is difficult to prevent without a deferredDispatch method, similar to that being explored in #598.
chrisvxd added a commit that referenced this pull request Sep 9, 2024
This will result in duplicate history entries if the item has a resolveData method. This is difficult to prevent without a deferredDispatch method, similar to that being explored in #598.
@princebansal
Copy link

@chrisvxd This sounds very exciting. Dnd kit will really be a good upgrade. May I know, if there are any estimates of when this will be ready to use. Both stable and beta version of it.

@chrisvxd
Copy link
Member Author

Thanks @princebansal - we don't have a timeline yet. It's slow progress as it's a non-trivial implementation.

I would like to get it out by end of October in v0.17, but that's not based on anything!

Causes a drop minor animation issue, which needs to be resolved upstream.
Previously, it was possible to have a null area even if a zone within it was active. This was likely due to nuances in the rendering, shadows or buffer zones. This would cause inconsistent behaviour and trigger deepest zone changes unexpectantly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants