radix-ui / primitives

Radix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by @workos.
https://radix-ui.com/primitives
MIT License
15.34k stars 765 forks source link

Draggable and onDragStart #2867

Open YousefED opened 4 months ago

YousefED commented 4 months ago

Bug report

I want to create a draggable element that also functions as DropdownMenuTrigger.

Unfortunately, I think the implementation opens the menu after an onPointerDown event. It seems that this is raised before the onDragStart event, which means that the submenu is always opened and we can't implement dragging behavior

Current Behavior

Drag event (onDragStart) is never fired, and the menu always opens when start dragging

Expected behavior

Only a Click should open the menu. Dragging should fire the onDragStart event

Misc

For context, what I'm trying to implement is similar to the "Drag handle" in Notion, where a click opens a menu, but the handle can also be dragged to drag blocks around:

image
NILAXY commented 3 months ago

Not having the ability to use dropdown or context menus on draggable items is a deal breaker for dashboards unfortunately

eli4n commented 3 months ago

This feature is critical for our project as well. Any updates on when it might be implemented? :)

reinvanimschoot commented 2 months ago

Is there any workaround for this?

markbenliyan commented 2 months ago

bump

markbenliyan commented 2 months ago

For folks also wondering, i suggest trying something like the following: Render the dropdown trigger but make it small / invisible, it just needs to be referenced for positioning. Then, render a button that is draggable, and has an onClick of opening the dropdown menu the way you'd expect.

Here's an example

<Dropdown.Root open={isDropdownOpen} onOpenChange={setIsDropdownOpen}>
  <div className="absolute top-0 -left-10">
    <button
      className="rounded-md bg-white text-gray-700 hover:bg-gray-0 hover:text-black p-2 shadow-sm cursor-grab"
      data-drag-handle={true}
      onClick={e => {
        e.preventDefault()
        e.stopPropagation()
        setIsDropdownOpen(true)
      }}
    >
      <Icon className="m-1" name="GripVertical" />
    </button>
    <Dropdown.Trigger className="absolute top-0 left-0 h-full w-full -z-10" />
  </div>
  <Dropdown.Portal>
    <Dropdown.Content>
        <div className="mt-2.5 first:mt-0 gap-0.5 flex flex-col">
          <Dropdown.Item>
            <span>Dummy Option 1</span>
          </Dropdown.Item>
          <Dropdown.Item>
            <span>Dummy Option 2</span>
          </Dropdown.Item>
        </div>
    </Dropdown.Content>
  </Dropdown.Portal>
</Dropdown.root>