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

Allow passing range option to useSwipeTransition #32412

Merged
merged 2 commits into from
Feb 21, 2025

Conversation

sebmarkbage
Copy link
Collaborator

Stacked on #32379

Track the range offsets along the timeline where previous/current/next is. This can also be specified as an option. This lets you model more than three states along a timeline by clamping them and then updating the "current" as you go.

It also allows specifying the "current" offset as something different than what it was when the gesture started such as if it has to start after scroll has already happened (such as what happens if you listen to the "scroll" event).

@react-sizebot
Copy link

react-sizebot commented Feb 18, 2025

Comparing: 88479c6...243bb8a

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB = 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 515.71 kB 515.71 kB = 92.09 kB 92.09 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.20% 564.52 kB 565.64 kB +0.29% 100.55 kB 100.84 kB
facebook-www/ReactDOM-prod.classic.js = 636.70 kB 636.70 kB = 112.08 kB 112.08 kB
facebook-www/ReactDOM-prod.modern.js = 627.02 kB 627.02 kB = 110.50 kB 110.49 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
test_utils/ReactAllWarnings.js +0.27% 63.34 kB 63.51 kB +0.45% 15.82 kB 15.89 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js +0.27% 432.99 kB 434.15 kB +0.37% 69.98 kB 70.25 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js +0.24% 485.96 kB 487.11 kB +0.36% 77.85 kB 78.13 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer.production.js +0.23% 36.58 kB 36.67 kB +0.23% 6.85 kB 6.86 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer.production.js +0.23% 36.61 kB 36.69 kB +0.22% 6.88 kB 6.89 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer.production.js +0.23% 36.62 kB 36.70 kB +0.22% 6.88 kB 6.90 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-persistent.production.js +0.23% 36.71 kB 36.80 kB +0.23% 6.87 kB 6.88 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-persistent.production.js +0.23% 36.74 kB 36.82 kB +0.22% 6.90 kB 6.91 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-persistent.production.js +0.23% 36.74 kB 36.83 kB +0.22% 6.90 kB 6.91 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer.development.js +0.22% 40.78 kB 40.87 kB +0.24% 7.44 kB 7.46 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer.development.js +0.22% 40.81 kB 40.90 kB +0.21% 7.47 kB 7.48 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer.development.js +0.22% 40.81 kB 40.90 kB +0.23% 7.47 kB 7.49 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +0.22% 40.92 kB 41.01 kB +0.24% 7.46 kB 7.47 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +0.22% 40.95 kB 41.04 kB +0.24% 7.49 kB 7.50 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +0.22% 40.95 kB 41.04 kB +0.23% 7.49 kB 7.51 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js +0.22% 722.28 kB 723.85 kB +0.34% 114.04 kB 114.42 kB
oss-experimental/react-art/cjs/react-art.production.js = 325.24 kB 324.15 kB = 55.62 kB 55.32 kB

Generated by 🚫 dangerJS against a9526df

…t is

Also, let you specify this as options. This lets you model more than three
states along a timeline by clamping them.

It also allows specifying the "current" offset as something different than
what it was when the gesture started such as if it has to start scroll has
already happened.
This avoids a case where we'd switch to previous when returning to 0 where
0 was also the starting point.
Comment on lines +4024 to +4034
currentOffset < rangeCurrent
? isFlippedDirection
: currentOffset > rangeCurrent
? !isFlippedDirection
: // Otherwise, look for an explicit option.
gestureOptions && gestureOptions.direction === 'next'
? true
: gestureOptions && gestureOptions.direction === 'previous'
? false
: // If no option is specified, imply from the values specified.
queue.initialDirection;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nested ternaries are tough to reason about here. Might be more readable in if blocks.

Took some stepping through to realize we only look for the gestureOptions.direction or queue.initialDirection if the currentOffset is the rangeCurrent. I had expected an explicit direction object to override when available. But I guess it makes sense to base off movement because even a one-way gesture needs to be able to reset if its pulled back the other way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see from the next PR that the movement may have started before the scroll event. Which the currentOffset can represent here.

@sebmarkbage sebmarkbage merged commit 662957c into facebook:main Feb 21, 2025
194 checks passed
github-actions bot pushed a commit that referenced this pull request Feb 21, 2025
Stacked on #32379

Track the range offsets along the timeline where previous/current/next
is. This can also be specified as an option. This lets you model more
than three states along a timeline by clamping them and then updating
the "current" as you go.

It also allows specifying the "current" offset as something different
than what it was when the gesture started such as if it has to start
after scroll has already happened (such as what happens if you listen to
the "scroll" event).

DiffTrain build for [662957c](662957c)
sebmarkbage added a commit that referenced this pull request Feb 21, 2025
Stacked on #32412.

To effectively `useSwipeTransition` you need something to start and stop
the gesture as well as triggering an Action.

This adds an example Gesture Recognizer to the fixture. Instead of
having this built-in to React itself, instead the idea is to leave this
to various user space Component libraries. It can be done in different
ways for different use cases. It could use JS driven or native
ScrollTimeline or both.

This example uses a native scroll with scroll snapping to two edges. If
you swipe far enough to snap to the other edge, it triggers an Action at
the end.

This particular example uses a `position: sticky` to wrap the content of
the Gesture Recognizer. This means that it's inert by itself. It doesn't
scroll its content just like a plain JS recognizer using pointer events
would. This is useful because it means that scrolling doesn't affect
content before we start (the "scroll" event fires after scrolling has
already started) so we don't have to both trying to start it earlier. It
also means that scrolling doesn't affect the live content which can lead
to unexpected effects on the View Transition.

I find the inert recognizer the most useful pairing with
`useSwipeTransition` but it's not the only way to do it. E.g. you can
also have a scrollable surface that uses plain scrolling with snapping
and then just progressively enhances swiping between steps.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants