Currently the library only supports keyboard and mouse dragging. It would useful to add touch support so that it can be used on touch devices (eg phones and tablets)
This feature would require some additional touch event handlers and management in drag-handle.jsx.
The challenges will be:
Draggable anchor (or some other interactive element) to operate as an anchor normally while also allowing users to drag it without the interactions overlapping unnaturally (similar to the sloppy click threshold)I did a little spike and I am not worried about performance at this stage. The current implementation is fairly light on the CPU while dragging
At this stage internally we are targeting a few features for our desktop applications:
So those will be the focus of our internal efforts for now as they are out immediate use cases. If somebody else wants to give it a crack let me know. I did a spike and it is fairly easy to add some touch listeners and get it all going. The challenge is making it feel great for users every time
Thanks for your work @alexreardon! Looking forward to this.
Hi thanks for the react-beautiful-dnd plugin, good job so far.
I wonder what way you are going to use for mobile dnd. On mobile the touch and move interaction is already used for scrolling. I see 3 ways:
We are looking at adopting a press and hold (long touch) mechanism to initiate touch dragging to avoid conflicts with normal scrolling. It is a similar pattern that is used in native devices. We are aiming to avoid providing any options for custom drag starting - similar to what we already do with mouse. We will investigate and decide on a approach that works well with the rest of the feature set and fits well in the physical metaphor we are going for. The long press seems nice because it is sort of like taking the time to pick something up.
/cc @jaredcrowe
We are hoping to look at this in the next few weeks! https://github.com/atlassian/react-beautiful-dnd/milestone/2
Yay! πππ
π€ I hope to start work on this when I return
Making progress π

The event binding code drag-handle.js was getting super hard to reason about. I have decided to split the event handling into three seperate sensors: mouse, keyboard and touch. This makes things a lot easier to reason about and avoids a lot of conditionals. I already have the mouse and keyboard back to parity with the original code. This change will significantly reduce the mental friction and maintenance burden.
Next week I will implement the touch sensor as well as ensuring all the old tests pass and that new tests are written for the new behaviour and touch sensor.
Note: this is an internal change and the api will remain the same
On top of the amazing work, thank you for these status updates. I, as someone interested in this feature, appreciate being in the loop about this progress.
Yes thank you @alexreardon and for the amazing library, your hard work, and updates! This will be very helpful :)
Glad you find them useful @mostafah @trevordmiller - I was not sure if people were interested
@alexreardon these updates are super helpful, cant wait to try out the mobile version. This react component is one of the best Ive seen, awesome job β¨ π
I am getting closer. I now have it working on latest mobile chrome, safari and firefox on ios11 π€.
In order to manage expectations I want to call out that this initial release will not support scrolling / auto scrolling. This means that when a Draggable moves to the edge of a scroll container or the viewport a scroll will not occur. This is obviously not ideal and will be addressed when we build #27 which should hopefully be quite soon. This is a similar restriction to what we already have in place for keyboard dragging. Auto scrolling is currently scheduled as the next feature to be built.
Chrome, Safari and Firefox


Things move forward and then backwards. The goal is to create an experience that feels great while also respecting the standard touch interactions as much as possible. Here is some in progress documentation:
When a user presses their finger (or other input) on a Draggable we are not sure if they where intending to tap, force press, scroll the container or drag. As much as possible react-beautiful-dnd aims to ensure that a users default interaction experience remains uneffected.
Draggable that is both clickable such as a anchor as well as draggable.Draggable. This is unfortunate but opting out of native scrolling can only be done before we know if it was a scroll or not. This is standard in drag and drop libraries but we wanted to call it outDraggable AnchorsIf the element you are dragging is an anchor <a> we recommend that you add the following styles:
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-touch-callout: none;
If you like you could also trigger a vibration event when the user picks up a Draggable. This can provide tactile feedback that the user is doing something. It currently is only supported in Chrome on Android.
class App extends React.Component {
onDragStart = () => {
// good times
if (window.navigator.vibrate) {
window.navigator.vibrate(200);
}
};
/*...*/
}
You can have a play with the new touch support here. Be sure to look on your touch device
Hey Alex, tried on a Pixel on Android 8.0.0.
When unscrolled I have to hold for a while before moving or it causes a refresh.
When scrolled down I cant seem to move at all. I'll show you tomorrow if you like. :$
Great. It works very good on iPhone (Safari on iOS 11.1, iPhone 7). The only problem is that I can only scroll with the blue area. Swiping over the cards does not do anything. Iβm not sure if that is expected for the first version or not.
I was able to long press, then start moving, but instead it scrolled the list below the card.
When I am towards the top of the page, this can cause the refresh trigger.
It seems to be based on timing because the card goes green and I think I can drag but maybe I am too fast?
A lot of times the long press doesn't grab the task, just selects it.
Android, Google Chrome.
We are trying to make a decision about how to start a touch drag. There are two primary options which would be great to get your vote on. Each option will get its own comment below. To add a vote add a π reaction to the comment. The votes won't be strictly binding - but it will be a great opportunity to see what other people think. Also, if you have other suggestions or would like to comment feel free to do so.
When a user puts their finger down (or some other touch input) we need to opt out of native scrolling. Unfortunately this decision needs to be made up front and we cannot opt back into native scrolling after this initial press.
If the user moves their finger beyond a threshold within a small period of time we can safely assume they where trying to scroll rather than drag. So we do not start a drag. However, this can confuse the user as the interface can feel unresponsive as they are trying to native scroll but we have already opted out of native scrolling.
This one is my current preference
If the user moves beyond a certain threshold (regardless of time): start a drag. This means that even if a user was trying to scroll: a drag will start. This might be annoying as the user may have been intending to scroll - but at least something will happen (a drag) rather than nothing in option 1. Given that we need to opt out of native scrolling I think this is the best option.
Also, keep in mind that once auto scrolling lands this experience will not be as bad.
Cheers
Vote: option 1 don't start a drag is a user is trying to scroll
(Even though a native scroll will not happen)
Vote: option 2 start a drag on scroll attempt
(My preference)
I am a little confused, would both options allow us to implement something like trello has in their mobile experience? (They've got both scrolling the lists and dragging the tasks)
@hakunin this has to do with drag initiation. Once auto scrolling is supported then you will be able to scroll no worries
Also, Trello's mobile web experience does not have card drag and drop
Ah, I was looking at their app, hoping its the same.
Yeah native is a little different. We can only achieve what the browsers / web standards let us π
@lukebatchelor @hakunin the experience on andriod is not great atm. I will be looking into it when I get more time
I have now swapped over to option 2 and it feels much better.
@hakunin @lukebatchelor I have added some improvements for android - please give it another go!
It's perfect Alex! The vibration is an awesome touch! (No pun intended??)
Great work on this! Iβm trying to follow along but Iβm missing a proper understanding of the interaction with native scrolling.
I think the reason for opting out is that we want the page to stay fixed (i.e. not scrolling) so that the Draggable is moved relative to the page rather than moving with it, is that right?
Iβm also curious out the method of opting out of native scrolling, and your thoughts on an approach like https://stackoverflow.com/a/17159809.
I also donβt know what the ideal state of starting a drag should be, whether itβs instant, force touch, touch and hold, or something else, and if youβre aiming to make the library opinionated and bake in support for one behaviour, or if youβre aiming to have it unopinionated and configurable.
@bradleyayers we cannot use native scrolling as the direction that a user moves an item to reorder it is often the different to the scroll direction for touch devices
Yes, we are opting out so the page stays fixed - at least until we support auto scrolling. The library will be opinionated - the idea is to interfere as little as possible with standard browser interactions while designing a drag and drop interaction that feels natural.
These styles are now baked into DraggableStyle and NotDraggingStyle as they provide a sensible default and have no visual impact. Consumers are welcome to opt out or change these values (although I suspect that would never be the case)
// These styles are applied by default to allow for a
// better touch device drag and drop experience.
// Users can opt out of these styles or change them if they really need too
// for their specific use case.
type BaseStyle = {
// A long press on anchors usually pops a content menu that has options for
// the link such as 'Open in new tab'. Because long press is used to start
// a drag we need to opt out of this behavior
'-webkit-touch-callout': 'none',
// Webkit based browsers add a grey overlay to anchors when they are active.
// We remove this tap overlay as it is confusing for users
// https://css-tricks.com/snippets/css/remove-gray-highlight-when-tapping-links-in-mobile-safari/
'-webkit-tap-highlight-color': 'rgba(0,0,0,0)',
// Added to avoid the *pull to refresh action* and *anchor focus* on Android Chrome
touchAction: 'none',
}
Thinking about this a bit more, I suppose https://stackoverflow.com/a/17159809 would only be useful if we wanted to go in the direction of "long press to lift draggable" UX. As in touch events would initially scroll the page, but if the user did not scroll beyond a small distance in our long-press-to-lift-duration, page scrolling would be "turned off" (by .preventDefault() on the touchmove events) and we'd lift the item and use the yet-to-be-implemented auto scrolling.
Basically it would be #1 but without the following, because the opt-out wouldn't happen up-front:
However, this can confuse the user as the interface can feel unresponsive as they are trying to native scroll but we have already opted out of native scrolling.
I think I'm still missing something though, because this isn't the approach you're going with. Is it:
@bradleyayers it is a little hard to follow. Here is my attempt to explain it a little further:
We now use the two following methods to check if a drag starts:
We also do a lot more work to ensure:
The decision was between whether we do nothing on a scroll or if we start a drag. Given that doing nothing sucks and feels broken we start the drag. The complication is the initial one time opt in / out decision.
Hopefully that provides some more information for you :)
Another plus for the approach that you chose: it makes sense with custom drag handles too. When the items have drag handles in them, dragging by drag handle should always work and Iβm guessing that scroll works by swiping outside of the drag handle. This is exactly what users expect.
@alexreardon now the demo works without issues. It would be nice if the task could highlight when I tap it (even before I start moving) because now it feels like there is a lag in the phone's response because of the movement threashold.
You are welcome to patch the event handlers to add a selected state but it will not come out of the box with the library. Tap has particular meanings such as navigation that we do not want to overwrite (although you are welcome to)
Thanks everyone in your encouragement getting this across the line!
π€
Closed by #165
Most helpful comment
Making progress π