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

Cursor type set for Draggable is not respected while dragging #109

Closed
pdkovacs opened this issue Sep 21, 2017 · 5 comments
Closed

Cursor type set for Draggable is not respected while dragging #109

pdkovacs opened this issue Sep 21, 2017 · 5 comments

Comments

@pdkovacs
Copy link

Bug or feature request?

Bug

Expected behaviour

  1. Move the mouse over a draggable. -> Cursor changes to grab.
  2. Start dragging. -> Cursor changes to grabbing.

Actual behaviour

Cursor is changing to grab as expected when mouse is moved over a draggable.
Cursor changes to default when a draggable is being dragged -- as opposed to exepcted grabbing.

Steps to reproduce

Add the following to the object returned by the getItemStyle function in the basic example (https://www.webpackbin.com/bins/-KuZVBLKLMq2RG9M5jkK)

  cursor: isDragging ? '-webkit-grabbing' : '-webkit-grab',
  1. Move the mouse over a draggable. -> Observe that the cursor changes to grab.
  2. Start dragging. -> Observe that the cursor changes to default.

Browser version

Chrome Version 60.0.3112.113 (Official Build) (64-bit)

Demo

Add the following to the object returned by the getItemStyle function in the basic example (https://www.webpackbin.com/bins/-KuZVBLKLMq2RG9M5jkK)

  cursor: isDragging ? '-webkit-grabbing' : '-webkit-grab',
@jaredcrowe
Copy link
Contributor

jaredcrowe commented Sep 22, 2017

Hey @pdkovacs, the reason this happens is because we actually apply pointer-events: none to all draggable items during a drag. This gives us a significant performance boost, but it does make styling the cursor a bit trickier. Here are some strategies for working around it:

1. Opt out of pointer-events: none on dragging items
This will impact performance but it's the simplest solution and you might be happy to live with it:
https://www.webpackbin.com/bins/-Kuafkdkl05YnwTOjyLA

const getItemStyle = (draggableStyle, isDragging) => ({
  // some basic styles to make the items look a bit nicer
  userSelect: 'none',
  padding: grid * 2,
  margin: `0 0 ${grid}px 0`,
  cursor: isDragging ? '-webkit-grabbing' : '-webkit-grab',

  // change background colour if dragging
  background: isDragging ? 'lightgreen' : 'grey',

  // styles we need to apply on draggables
  ...draggableStyle,

  // opt out of pointer-events: none for dragging items
  ...(isDragging && { pointerEvents: 'auto' })
});

One thing you might notice with this approach is that when you move the mouse around quickly during a drag it'll periodically move outside the bounds of the draggable, and you'll see the cursor flicker. This isn't ideal, so we don't recommend this strategy.

2. Apply the cursor style to the entire page during a drag
https://www.webpackbin.com/bins/-KuaxsuzVy0qPCjjnxSV
We listen to the DragDropContext's onDragStart and onDragEnd hooks and keep track of the isDragging state at the application level. This state can then be used to apply the grabbing cursor style to a root-level element during a drag. A benefit of this approach is that you won't get any flickering if the cursor moves outside the dragging item because the entire page gets the cursor style. This is the approach we use in our stories, so take a look at the storybook code for specifics on our implementation. We use styled-components, so it's a bit different from the WebpackBin demo I provided, but the principle is the same.

@alexreardon
Copy link
Collaborator

alexreardon commented Sep 22, 2017

I would advise solution 2. We advise this in the readme. Opting out of pointer-events: none will prevent the user from scrolling the list behind the Draggable with their mouse. Also, applying the cursor style to the body avoids the cursor changing of the user slips their mouse off the Draggable. This is possible as all Draggable movements are throttled with request animation frame and might move slower than the users cursor if they are moving very quickly.

Solution 1 is actually a bit dangerous as we do not test that this will work. Setting pointer events: none is a super important optimisation. If you really need to set the cursor on the element itself - then I would only opt out of cursor events: none for the dragging item only and not the others. But, the overwhelming priority would be solution 2 (apply cursor style to the page)

I hope that helps!!

@alexreardon
Copy link
Collaborator

@pdkovacs
Copy link
Author

pdkovacs commented Sep 22, 2017

Thanks to both of you for your help, in particular to @jaredcrowe for the excellent example!

@tqdo
Copy link

tqdo commented Oct 20, 2021

@alexreardon @jaredcrowe all the links mentioned above do not work anymore. Do you mind sharing the updated links to change the style of the cursor? I add cursor: move to draggableStyle and the cursor style changes when hovering, but does not change when dragging. Thanks.

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

No branches or pull requests

4 participants