React-dnd: Customize the cursor during drag

Created on 5 Nov 2015  ·  15Comments  ·  Source: react-dnd/react-dnd

Fantastic library! Thanks for all your hard work in putting it together. I have a quick question: is it possible to customize the cursor such that during a drag operation, the cursor is always set to the same thing (specifically I want to set it to the _dragging_ icon)?

In other words, regardless of whether you are over a drop zone or not, the cursor remains the same. This is similar to how Trello has the cursor while dragging a note, for example.

Thanks in advance!

question

Most helpful comment

Anyone managed to resolve this?

All 15 comments

You can probably set a cursor style on the whole body (or application root div) while isDragging is true. You can use DragLayer to listen to isDragging changes.

Thanks, I wish that worked! Unfortunately, the cursor style is overridden by something (I'm on Chrome), even when setting the cursor style to document.body and marking it as "!important". Any other ideas?

Maybe it's just how HTML5 drag and drop API works. In this case the only solution is to create a custom backend that uses mouse events instead of HTML5 drag and drop events.

I was hoping you wouldn't say that :) Thanks!

I've just found out about this issue. Unfortunately, it seems not posible to change the icon while dragging :(

Anyone managed to resolve this?

Also went and looked into this. Yes it seems that this is sadly a browser limitation in that the API for DataTransfer.effectAllowed only supports a handful of options:

https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed

So the only way to get around this is, as @gaearon mentioned, which is to use a different custom backend :/ This might be something worth including in the HTML5 backend documentation as that might not be something intuitive to people.

Well a very wrong but working solution would be adding a dragging class to the body so that body and every DOM Object inside the body will get cursor: grabbing !important. Nothing will than override it.
This is what worked for me:

:global {
    body.dragging,
    body.dragging * {
        cursor: url('./assets/cursors/grabbing.cur'), move !important;
    }
}

Another approach using JS could be something like this:

window.addEventListener('drag', () => {
  document.body.style.cursor = 'grabbing';
}, true)

It doesn't seem to be working consistently though...

I can't get any of the suggested solutions here to work. Anything update on this?

Switching to TouchBackend & using css to set cursor worked for me.

<DndProvider backend={TouchBackend} options={{ enableTouchEvents: false, enableMouseEvents: true }}>
  <div className=`my-app ${isDragging ? 'dragging' : ''}`>
      .... draglayers here
  </div>
</DndProvider>
.dragging {
  cursor: grabbing
}

Switching to TouchBackend & using css to set cursor worked for me.

<DndProvider backend={TouchBackend} options={{ enableTouchEvents: false, enableMouseEvents: true }}>
  <div className=`my-app ${isDragging ? 'dragging' : ''}`>
      .... draglayers here
  </div>
</DndProvider>
.dragging {
  cursor: grabbing
}

not working for me

+1

someone managed to resolve this?

Switching to TouchBackend & using css to set cursor worked for me.

<DndProvider backend={TouchBackend} options={{ enableTouchEvents: false, enableMouseEvents: true }}>
  <div className=`my-app ${isDragging ? 'dragging' : ''}`>
      .... draglayers here
  </div>
</DndProvider>
.dragging {
  cursor: grabbing
}

switching to TouchBackend worked for me

DnD provider:

import { DndProvider } from 'react-dnd';
import { TouchBackend } from 'react-dnd-touch-backend';

...
<DndProvider backend={TouchBackend} options={{enableMouseEvents: true}}>
...
</DndProvider>

Drag handlers implementation:

    import { useDrag, useDrop } from 'react-dnd';
    ....

    const [...] = useDrag({
      ...
      begin: () => {
        document.body.classList.add('dragging');
        ...
     },
      end: () => {
        document.body.classList.remove('dragging');
        ...
      },
    });

css file

   body.dragging: {
      cursor: crosshair !important;
   },
Was this page helpful?
5 / 5 - 1 ratings