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

Customize the cursor during drag #325

Closed
dshorowitz opened this issue Nov 5, 2015 · 22 comments
Closed

Customize the cursor during drag #325

dshorowitz opened this issue Nov 5, 2015 · 22 comments
Labels

Comments

@dshorowitz
Copy link

@dshorowitz dshorowitz commented Nov 5, 2015

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!

@gaearon
Copy link
Member

@gaearon gaearon commented Nov 6, 2015

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.

@gaearon gaearon closed this Nov 6, 2015
@dshorowitz
Copy link
Author

@dshorowitz dshorowitz commented Nov 6, 2015

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?

@gaearon
Copy link
Member

@gaearon gaearon commented Nov 6, 2015

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.

@dshorowitz
Copy link
Author

@dshorowitz dshorowitz commented Nov 6, 2015

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

@gazpachu
Copy link

@gazpachu gazpachu commented Aug 12, 2016

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

@alexeymolchan
Copy link

@alexeymolchan alexeymolchan commented Jul 26, 2017

Anyone managed to resolve this?

@augbog
Copy link

@augbog augbog commented Aug 7, 2017

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.

@larspa
Copy link

@larspa larspa commented Feb 7, 2018

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;
    }
}

@simonewebdesign
Copy link

@simonewebdesign simonewebdesign commented May 10, 2019

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...

@dwilt
Copy link

@dwilt dwilt commented Aug 19, 2019

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

@nathanbrud
Copy link

@nathanbrud nathanbrud commented Sep 15, 2019

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
}

@niron1
Copy link

@niron1 niron1 commented Nov 14, 2019

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

@jinxin0112
Copy link

@jinxin0112 jinxin0112 commented Apr 10, 2020

+1

@shiranZe
Copy link

@shiranZe shiranZe commented Jun 4, 2020

someone managed to resolve this?

@kurochkinSergei
Copy link

@kurochkinSergei kurochkinSergei commented Jul 15, 2020

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;
   },

@FullstackJack
Copy link

@FullstackJack FullstackJack commented Jan 28, 2021

Amazing that the TouchBackend actually worked using the solution outlined by @kurochkinSergei. Hopefully that doesn't introduce any regressions.

@MoSheikh
Copy link

@MoSheikh MoSheikh commented Mar 11, 2021

Anyone have any success with this at all? Setting the document.body class does not work using HTML5 backend.

@FermiDirak
Copy link

@FermiDirak FermiDirak commented Oct 6, 2021

Found a working solution. The trick is to update the draggable element's cursor style when the element isDragging.

function MyDraggableComponent () {
  const [{ isDragging }, drag] = useDrag(() => ({
    ...
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  }));
  
  return (
    <div ref={drag} style={{cursor: isDragging ? 'grabbing' : 'grab' }}>
      Draggable Element
    </div>
  );
}

See this minimum reproduction of the problem and the solution below:
https://codesandbox.io/s/tender-ives-bie31?file=/src/Knight.tsx:649-700

@hmeyerx
Copy link

@hmeyerx hmeyerx commented Oct 18, 2021

Found a working solution. The trick is to update the draggable element's cursor style when the element isDragging.

function MyDraggableComponent () {
  const [{ isDragging }, drag] = useDrag(() => ({
    ...
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  }));
  
  return (
    <div ref={drag} style={{cursor: isDragging ? 'grabbing' : 'grab' }}>
      Draggable Element
    </div>
  );
}

See this minimum reproduction of the problem and the solution below: https://codesandbox.io/s/tender-ives-bie31?file=/src/Knight.tsx:649-700

That codesandbox doesn't seem to work in Chrome 93.0.4577.82 (cursor not set to grabbing).

@nahumzs
Copy link

@nahumzs nahumzs commented Oct 21, 2021

@FermiDirak I just the tested the codesandbox on chorme 94.0.4606.81` and seems ok tome @hmeyerx

@hmeyerx
Copy link

@hmeyerx hmeyerx commented Oct 22, 2021

2021-10-21 18 10 35

@FermiDirak I just the tested the codesandbox on chorme 94.0.4606.81` and seems ok tome @hmeyerx

is this different from what you're seeing?

@cyberscorpion
Copy link

@cyberscorpion cyberscorpion commented Dec 22, 2021

Any working solution for this in Chrome and Safari together?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet