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

Exclude children from the gesture #433

Open
dbismut opened this issue Jan 25, 2022 Discussed in #428 · 8 comments
Open

Exclude children from the gesture #433

dbismut opened this issue Jan 25, 2022 Discussed in #428 · 8 comments
Labels
enhancement New feature or request

Comments

@dbismut
Copy link
Collaborator

dbismut commented Jan 25, 2022

cc @odusseys

Discussed in #428

Originally posted by odusseys January 19, 2022
Hi,
Is there a way to exclude specific children of an element from triggering the gesture / getting events as they should ? For example, is there a way to correctly select text within a draggable elements ?

@dbismut dbismut added the enhancement New feature or request label Jan 25, 2022
@odusseys
Copy link

odusseys commented Jan 25, 2022

Responding to your last comment: it doesn't feel very idiomatic (in a react sense, but I understand the lib is meant to work for all JS frameworks including vanilla) to

  • be passing around / working with dom objects unless it's a last resort / building a library, so as a consumer of a react lib it is always much more appreciable to work with components, hooks and refs
  • send objects bottom-up in the props hierarchy. This to me is the biggest issue ; if the component you wish to exclude is nested deep, you will need to forward a ref multiple times down to that component in order for it to be used (or put it in a context ; but putting refs in a context is clunky). In particular refactoring becomes much more complex, and the props are muddled by an unneccessary ref which has little to do with the intrinsic purpose of the components.

For react, this use case seems to be most compatible with the Context API ; ie a provider at the useGesture level (useGesture and the child component would both subscribe to this context to communicate)

For the general vanilla JS purpose, I would rely on an element property (ex. use-gesture-ignore="true"), or something along those lines. This is less ideal for React as custom properties are not idiomatic, and don't work in a straightforward way if you want to wrap a fragment / list.

I find the react-dnd lib extremely well designed in this aspect, it allows to very easily and modularly communicate between drag / drop components without any prop sharing whatsoever.

@dbismut
Copy link
Collaborator Author

dbismut commented Jan 25, 2022

Can you point at where react-dnd is using the context api? Honestly it feels a bit convoluted to be using a <Provider /> for a lib such as use-gesture, but I'm happy to reconsider.

@odusseys
Copy link

the provider could be used optionally (only if you need a child to get access to the gesture / the gesture state)
react-dnd has the provider here https://react-dnd.github.io/react-dnd/docs/api/dnd-provider
but it's a bit different since all hooks / HOC subscribe to this provider, as a means to declare useDrag anywhere inside and useDrop anywhere else, and have both communicate without passing any props across.

@dbismut
Copy link
Collaborator Author

dbismut commented Jan 29, 2022

Would you be up for a PR? Note that the core package is platform agnostic (ie not React specific).

@odusseys
Copy link

odusseys commented Feb 4, 2022

I am under water with work but I'm putting a task in my todos to do this as soon as things clear out, would love to help

@plalance
Copy link

I personnally use @vueuse/gesture based on this library...

I have the same problem : my users want to still select texts or have a "normal" behavior of the website.

As i didn't found anything in gesture options and as the "target" option juste do nothing (= event still triggered on children)

what i did is basically check if the dom element of the state.event is the one i want based on classList..contains(example) and element.id = the one i want..

Example :

const handler = (state: any): void => {

  // boolean : check if target element is a div.pannel or a div.page => other elements should not trigger swipe.
  let isCorrectDomTriggered =
      state.event.target.classList.contains('page') ||
      state.event.target.classList.contains('pannel') ||
      state.event.target.id == 'app_body';

  if(!isCorrectDomTriggered)
    return

  // other stuff = when correct dom triggered

}

// Composable usage
// https://gesture.vueuse.org/use-drag.html#options
useDrag(handler, {
domTarget: draggy,
filterTaps: true,
axis: 'x'
});

Maybe someone will have a more elegant way to achieve this...
Have a good day :)

@devcer
Copy link

devcer commented Mar 23, 2023

cardRef.current.style.top = `${element.pageY + state.offset[1]}px`;
cardRef.current.style.left = `${element.pageX + state.offset[0]}px`;

I tried the same logic but the state offset still seems to be getting updated even though the draggable element didn't get dragged. So when I actually drag the element there is a sudden jerk.

@clearly-outsane
Copy link

I personnally use @vueuse/gesture based on this library...

I have the same problem : my users want to still select texts or have a "normal" behavior of the website.

As i didn't found anything in gesture options and as the "target" option juste do nothing (= event still triggered on children)

what i did is basically check if the dom element of the state.event is the one i want based on classList..contains(example) and element.id = the one i want..

Example :

const handler = (state: any): void => {

  // boolean : check if target element is a div.pannel or a div.page => other elements should not trigger swipe.
  let isCorrectDomTriggered =
      state.event.target.classList.contains('page') ||
      state.event.target.classList.contains('pannel') ||
      state.event.target.id == 'app_body';

  if(!isCorrectDomTriggered)
    return

  // other stuff = when correct dom triggered

}

// Composable usage // https://gesture.vueuse.org/use-drag.html#options useDrag(handler, { domTarget: draggy, filterTaps: true, axis: 'x' });

Maybe someone will have a more elegant way to achieve this... Have a good day :)

this worked for me but idk if its ideal

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

No branches or pull requests

5 participants