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

touch-action doesn't allow for press-hold-drag UX #178

Open
RByers opened this issue Feb 17, 2017 · 19 comments
Open

touch-action doesn't allow for press-hold-drag UX #178

RByers opened this issue Feb 17, 2017 · 19 comments
Assignees
Labels

Comments

@RByers
Copy link
Contributor

RByers commented Feb 17, 2017

In some mobile UX the user can scroll by swiping and also hold their finger for awhile to "pick up" an item which they can then drag around. Since you can't changetouch-action after the pointerdown (but before the finger has moved enough to actually scroll), this sort of UX can't be built with pointer events.

I suppose one answer is that such UX should just be built using HTML5 DnD primitives, and I am a little ashamed that this works on Edge but not Chrome ;-). But I think there's still an argument for allowing sites to build their own "press-hold-drag" behavior.

I wonder if we could relax the touch-action rules such that the page could still change the value right up until the action has actually started?

@jacobrossi @teddink did you ever run into any complaints about this?

/cc @staktrace @dtapuska

@staktrace
Copy link

Allowing the touch-action rule to change later would be a fairly involved change in Gecko. Would it be possible to instead add another touch-action value that explicitly designates this as the desired behaviour? e.g. touch-action: pan-x pan-y draggable would allow panning normally, but if a long-press is done it goes into "draggable" mode and disallows panning.

@RByers
Copy link
Contributor Author

RByers commented Feb 22, 2017

@staktrace thanks, yeah I was starting to think in that direction too. It's also pretty hard for developers to reason about when a touch-action change will and will not take effect.

I like the idea of draggable - it's consistent with touch-action talking about "actions" not the "gestures" that trigger them. Still the app needs to know when exactly that kicks in. Would we want to define a new pointertouchdragstart event or something? That could be confusing with HTML DnD. Maybe we could just say that a "drag" starts immediately after a canceled contextmenu event for a touch pointer? That perhaps argues for #100 (so you can easily check the pointerType from the contextmenu listener).

@staktrace
Copy link

I don't have a strong feeling either way with respect to firing a new event vs saying it triggers immeditaely after a canceled contextmenu event. I slightly prefer the former as it is more explicit and doesn't bake in an implicit assumption about what touch-gesture triggers the contextmenu.

@RByers
Copy link
Contributor Author

RByers commented Feb 22, 2017

Yeah baking in an assumption that the same gesture triggers contextmenu and touch dragging probably isn't ideal (though I expect it to be true on all browsers / platforms).

Anyway I don't think this is urgent - I'll add links here as a discover people needing to use (non-passive) touch events for such cases instead of pointer events (or passive touch events). It seems like it shouldn't be too hard to define a solution if we collect enough evidence of the importance of the issue.

@RByers
Copy link
Contributor Author

RByers commented Jun 1, 2017

Talked about this on the Chrome team with @dtapuska @flackr @NavidZ and @tdresser. We agree that the touch-action keyword should be a flag, eg. so that you can have both touch-action: pan-x pan-y draggable and touch-action: pan-y draggable (eg. in case you have a horizontal image carousel that also supports from drag-and-drop case).

However we'd rather use a term like unless-long-press (or eg. unless-hold) to be consistent in focusing on the browser actions (not what JS might do with the events) and imply that the listed touch-actions are permitted unless the user first does a long-press. If the user starts panning, then you get pointercancel and no events like normal for touch-action: auto. But if, before panning, the user holds their finger down, then you get this event followed by pointermoves as for touch-action: none

Open questions

  • Precise touch-action token name - unless-long-press, unless-hold etc?
  • Presumably the event name will follow the touch-action name, right? Eg. pointerlongpress, pointerhold, but do we want to explicitly add the touch word to make it clear it applies only to devices where touch-action applies? Eg. pointertouchhold seems pretty decent to me.
  • We want this completely separate from higher-level concepts like HTML DnD and contextmenu right? I think it's best to think of this as a low-level primitive API.
  • Does cancelling pointertouchhold prevent browser native behavior that follows from a hold like the context menu (and associated generation of contextmenu event)? I'd argue it should.

@NavidZ said he'd look into this a little further.

@RByers
Copy link
Contributor Author

RByers commented Jun 1, 2017

I should add that this seems important for Facebook. They've had to go back to using non-passive touch listeners in order to support their "Like" button where you can still scroll by starting on the button, but if you long-press it you get additional options for your "reaction". That's apparently the only case keeping Facebook from getting non-blocking scrolling, and (given the large amount of scrolling that occurs on Facebook) this makes it pretty urgent for the Chrome team. We might have a touch-event-specific workaround (/cc @dtapuska) but it would still be a shame if such scenarios required touch events because they were entirely impossible with pointer events.

/cc @bgirard

@RByers
Copy link
Contributor Author

RByers commented Sep 8, 2017

#216 suggests what seems like both a simpler and more powerful solution this class of "dwell gesture" problems. Please weigh in there.

@RByers
Copy link
Contributor Author

RByers commented Sep 8, 2017

One potential advantage to sticking with touch-action for this problem is that it may be easier to adopt for sites using passive Touch Events without switching to Pointer Events. But since we concluded above we'd really need a new event type anyway, I'm not sure there's really much benefit.

@piotr-cz
Copy link

piotr-cz commented Oct 5, 2017

I'm facing exactly same problem, as @RByers described:
In the app I'm working on users should be able to move elements inside a scrollable container.

As soon as touchstart fires, container should lock it's position so user is able to drag elements, without panning around.

It's not possible to achieve by adding the touch-action: none; property - it has no effect after touchstart.
Two possible workaround I found are:

  • register touchstart event implicitly as non-passive and run preventDefault inside a listener
  • change to overflow: hidden for scrollable container (scrollbars disappear and layout changes)

@dmitryshimkin
Copy link

dmitryshimkin commented Dec 5, 2019

I have a similar issue when trying to implement a custom horizontal pan gesture. I have a pointerdown event handler that subscribes to pointermove and pointerup events once triggered. In the pointermove handler I check how far and in what direction the user has moved the pointer. If the direction is horizontal I "start" the gesture. At this moment I want to disable default behaviour such as scrolling. I wish I could simply set touch-action: none to the scrollable element, but unfortunately it doesn't work as pointerdown event was already fired. As a result, it is not possible to disable scroll during horizontal panning which leads to terrible user experience.

@mustaqahmed
Copy link
Member

@dmitryshimkin: Does your custom behavior involve a press-and-hold gesture? If not, please file a new issue to keep this issue focused on press-hold-drag. And please also elaborate why touch-action: pan-y doesn't work for you. Thanks.

@patrickhlauke
Copy link
Member

Mentioned briefly during today's PEWG call - will review this for next meeting, but personally get the feeling that this may not make it properly into v3. addition of a new touch-action may be something that could also be considered as addition to https://compat.spec.whatwg.org/#touch-action / may require some incubation/experimentation first

/cc @smaug---- @NavidZ @liviutinta

@patrickhlauke
Copy link
Member

@NavidZ @liviutinta @smaug---- are we ok to close this, do you think?

@NavidZ
Copy link
Member

NavidZ commented Dec 15, 2020

I agree that this is a real problem and needs a solution. But as you suggested in needs more experimentation and incubation first. So if we keep in more like in the backlog might be better than just closing it.

@patrickhlauke patrickhlauke added future and removed v3 labels Dec 15, 2020
@skedwards88
Copy link

Are there any updates on this?

I'm running into a similar issue where the user touches down on an element and then moves to a neighboring element while still touching. The pointerover and pointerenter events fire when the user touches the first element, but not when the user moves the pointer to the neighboring element. I would like to know when the pointer enters any element, regardless of whether the touch started in that element. (If the pointer element is a mouse instead of touch, this point and drag behavior does work as I expect.)

@RByers
Copy link
Contributor Author

RByers commented Feb 3, 2022

Hi @skedwards88, for that I think you just need to releasePointerCapture. See https://w3c.github.io/pointerevents/#pointer-capture. What you're seeing is a direct result of the tradeoff we made here, sorry for the confusion it causes!

@flackr
Copy link
Contributor

flackr commented Feb 3, 2022

I suppose one answer is that such UX should just be built using HTML5 DnD primitives, and I am a little ashamed that this works on Edge but not Chrome ;-). But I think there's still an argument for allowing sites to build their own "press-hold-drag" behavior.

I'm wondering what press-hold-and-drag behaviours couldn't be built using HTML5 DnD primitives. I.e. if you set an empty dragImage and listen to drag events it might be possible to build completely custom rich drag interfaces which rely on the native platform timing for when to start drag (just as you would with contextmenu).

@RByers
Copy link
Contributor Author

RByers commented Feb 3, 2022

I'm wondering what press-hold-and-drag behaviours couldn't be built using HTML5 DnD primitives. I.e. if you set an empty dragImage and listen to drag events it might be possible to build completely custom rich drag interfaces which rely on the native platform timing for when to start drag (just as you would with contextmenu).

I'd love to know too. Want to whip up some demos? Last time I played with the DnD API and touch (many years ago) I struggled with various edge cases in the DnD behaviour and differences between browsers. But maybe I just didn't try hard enough or maybe it's better now?

@skedwards88
Copy link

Thank you for the suggestion to use releasePointerCapture @RByers ! That seems to work. For anyone in the same situation, I posted code samples here: https://stackoverflow.com/questions/70973822/no-pointerenter-event-if-you-touch-and-then-move-into-element/70976017#70976017

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

No branches or pull requests

9 participants