-
Notifications
You must be signed in to change notification settings - Fork 587
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
feat: Add swipe-to-interact functionality to Swipeable
component
#10912
feat: Add swipe-to-interact functionality to Swipeable
component
#10912
Conversation
|
||
const FRICTION = 1.2 | ||
const SWIPE_TO_INTERACT_THRESHOLD = 80 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the threshold up to which the distance from the screen edge the user has to swipe to trigger the action.
onLayout={(event) => { | ||
width.value = event.nativeEvent.layout.width | ||
}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm using the component's width to determine when the dragX
of the drag interaction has reached the end of the component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I follow the need for this extra function, I think the Reanimated element already provides onSwipeableOpen, where we can control kinda the same of actionOnSwipe
without any extra code. Then it's up to the caller to control it and the swipeable element stays simpler and more performant.
Maybe my PR description wasn't very clear. This new functionality is about swiping until the end without tapping on the action button (The Jira ticket has a video and better description of the interaction). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah it makes sense, not sure about the UX since there's nothing on the DS, looks legit just one thing we might consider to change.
progress: SharedValue<number>, | ||
const width = useSharedValue(0) | ||
|
||
const [hasSwiped, setHasSwiped] = useState(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be replaced by useRef from what I see in the code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried to make it work but it doesn't.... Is this what you would suggest?
const hasSwiped = useRef(false)
const handleSwipeToInteract = () => {
hasSwiped.current = true
}
useEffect(() => {
if (!hasSwiped.current) return
actionOnSwipe?.()
}, [hasSwiped.current])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that won't work because your useEffect comes from the state change reaction when we call `runOnJs. What could work is:
// no useEffect anymore
const handleSwipeToInteract = () => {
hasSwiped.current = true
actionOnSwipe?.()
}
// line 51
if (!actionOnSwipe || hasSwiped.current || !width.value) return {}
// line 56
runOnJs(handleSwipeToInteract)()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot, that's very clean! Of course, with the ref, there is no need for the effect anymore. I've updated the code 👍
You are right, the UX might change. The designs for the new home view's Tasks/Notifications section are still wip... |
const hasSwiped = useRef(false) | ||
|
||
const handleSwipeToInteract = () => { | ||
hasSwiped.current = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To prevent calling the action more than once.
@olerichter00 - Is there any way to make it so that element doesn't just vanish? Looks a bit clunky just popping out like that. In Moti, there's an
We should lean on that, even if its a simple opacity. But better: animate the height of the container to |
@damassi, yes, there are a couple of options like LayoutAnimation, Disappearable, HeighTransition, or Animated.Flastlist that can be used to animate the item disappearing. Because it might depend on the context (e.g. list vs single item), I thought it would be good not to build the animation into the |
Ah, that makes sense 👍 |
This PR resolves EMI-2127
Description
This PR adds swipe-to-interact functionality (swiping until the end without tapping on the action button) to the
Swipeable
component. We might fine-tune the interaction later after testing it on a real device.Simulator.Screen.Recording.-.iPhone.15.Plus.-.2024-10-09.at.08.55.38.mp4
PR Checklist
To the reviewers 👀
Changelog updates
Changelog updates
Cross-platform user-facing changes
iOS user-facing changes
Android user-facing changes
Dev changes
Swipeable
component (not used yet) - oleNeed help with something? Have a look at our docs, or get in touch with us.