Set cursor to the grabbing hand when gesture is active
😎
cursor: grab;
Added in 2.6.1 😎
Note that this change is available in new web implementation. To enable it, call enableExperimentalWebImplementation() in the root of your project.
Why is this desirable? I just encountered the behavior and I don't want it, and not seeing a way to turn it off.
@TomSwift I agree, and I've come up with a workaround to turn it off:
- Find the view that your
GestureDetectorwraps and get arefto it. - In every gesture's
onBegin, setviewRef.current.style.cursor = 'auto';
For example:
const viewRef = useRef<Animated.View>(null);
/* ... */
const panGesture = Gesture.Pan()
.onBegin(() => {
// Web fix: don't use the grabby hand when drawing.
if (Platform.OS === 'web' && viewRef.current !== null) {
(viewRef.current as unknown as HTMLElement).style.cursor = 'auto';
}
})
/* ...more config */;
/* ... */
<GestureDetector gesture={panGesture}>
<Animated.View ref={viewRef} /* ...more props */>
This works because they set the cursor to 'grab' right after calling activate(), and I think that's always followed by the state being transitioned to BEGIN.
Edit: hrm, actually I'm not sure if that's enough. I actually was doing something a bit more complicated:
const panGesture = Gesture.Exclusive(
Gesture.Pan()
.onBegin(() => {
// Web fix: don't use the grabby hand when drawing.
if (Platform.OS === 'web' && viewRef.current !== null) {
(viewRef.current as unknown as HTMLElement).style.cursor = 'auto';
}
})
.minDistance(0)
/* ...more config */,
Gesture.Tap()
.onBegin(() => {
// Web fix: don't use the grabby hand when drawing.
if (Platform.OS === 'web' && viewRef.current !== null) {
(viewRef.current as unknown as HTMLElement).style.cursor = 'auto';
}
})
);
This works. I seem to need the Tap - even if it does nothing at all. I also seem to need the minDistance(0), which you might not want. I'm afraid I haven't been able to distill it down to exactly the right fix to undo their change - maybe you'll have more luck.
Edit 2:
It appears that adding in the extra (unused) Gesture.Tap, at lower priority to your main gesture (via Gesture.Exclusive) seems to be the magic fix. I also needed the fix in the onUpdate part of my Gesture.Pan, but if your gesture wasn't a Gesture.Pan I'm sure you can do something similar. To be clear, I don't understand why this works.
let panGesture: GestureType | ComposedGesture = Gesture.Pan()
.onUpdate(event => {
// Web fix: don't use grabby hand (part 1)
if (Platform.OS === 'web' && viewRef.current !== null) {
(viewRef.current as unknown as HTMLElement).style.cursor = 'auto';
}
/* ...more code */
})
/* ...more config */;
// Web fix: don't use grabby hand (part 2)
if (Platform.OS === 'web') {
panGesture = Gesture.Exclusive(
panGesture,
Gesture.Tap().onBegin(() => {
if (viewRef.current !== null) (viewRef.current as unknown as HTMLElement).style.cursor = 'auto';
})
);
}
Edit 3:
If you are using manual activation, it's super simple: just put this code immediately after calling activate(). E.g.
const gesture = Gesture.Manual()
.onTouchesDown((event, manager) => {
/* ... logic */
manager.activate();
if (viewRef.current !== null) (viewRef.current as unknown as HTMLElement).style.cursor = 'auto';
};
All the hacks in the rest of my comment are to do with trying to find where each gesture calls activate() under the covers.
Hi @TomSwift and @chriscoomber! We understand that this change may not be desirable and not everyone likes the idea. With that in mind I've prepared this PR, which adds activeCursor prop. This way cursor keeps default appearance and if you would like to change it, you can use new prop to give it any css cursor value you'd like. I hope this will help!