Skip to content

refactor(motion): one release policy, resolveSnapPoint, on selectSnapPoint - #8663

Merged
cixzhang merged 1 commit into
mainfrom
feat/resolve-snap-point
Oct 27, 2026
Merged

cixzhang merged 1 commit into
mainfrom
feat/resolve-snap-point

Conversation

@cixzhang

Copy link
Copy Markdown
Contributor

User impact

None directly: no behavior changes. Where a drag's release lands (a sheet's detent, a pager's page, a snap point) is now decided by one internal helper, so every gesture that settles on a set of positions, including the upcoming public drag-to-snap-points API, follows the same rules instead of each keeping its own copy.

Change

  • motion/resolveSnapPoint.ts (new, internal) is the release policy, on the existing selectSnapPoint primitive:
    • A slow release lands on the snap point nearest where it would come to rest (its position, or its projected coast).
    • A flick (flickThreshold or faster) goes at least to the next snap point in its direction.
    • With start, a release moving back toward where the drag began cancels to it (AST-094 FR37).
    • With fromIndex and maxSteps, it moves at most that many points (a pager's one page per release).
  • motion/projection.ts keeps selectSnapPoint as the math primitive. Paging moves out to motion/selectPage.ts, which is built on resolveSnapPoint.
  • README rows are updated. The changeset is internal ([chore]).

Nothing on main imports paging from projection.ts, and resolveSnapPoint is not exported from the package (a test locks that).

Relationship

This is the motion half of #8565, split out so it can land on main ahead of the bottom-sheet stack. #8565 keeps only the bottom sheet's adoption. The public createDragToSnapPoints (#8658) can then call resolveSnapPoint instead of carrying its own copy of the same rules.

Testing

  • Core tsc: clean.
  • The motion suite passes (549), including resolveSnapPoint.test.ts (flick, cancel, step limit, projection, tolerance, ties) and selectPage.test.ts.
  • check:changesets is clean, and ESLint is clean on the changed files.

…Point

Where a release lands is decided in one place: motion/resolveSnapPoint.ts.
A slow release lands on the snap point nearest where it would rest; a flick
(flickThreshold or faster) goes at least to the next snap point in its
direction; with start, a release moving back toward it cancels to it
(spec:AST-094 FR37); with fromIndex and maxSteps it moves at most that many
points. selectSnapPoint in projection.ts stays the math primitive, and
paging moves to selectPage.ts on top of resolveSnapPoint. Internal: not
exported from the package (a test locks that). No behavior change.

Split from #8565 so the public drag-to-snap-points API can build on it;
#8565 keeps the bottom sheet's adoption.
@vercel

vercel Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 27, 2026 7:52am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 27, 2026, 8:17 AM UTC

@github-actions

Copy link
Copy Markdown
Contributor

PR Analysis Report

Current run: The current CI run concluded cancelled. Current analysis is unavailable.

View Storybook for this PR · View Sandbox for this PR


Generated by PR Enrichment workflow | View current CI run

vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…snap points

The motion README keeps this branch's Files table and takes meta#8663's rows:
resolveSnapPoint.ts and selectPage.ts, and projection.ts without paging.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…se policy says

The factory now calls resolveSnapPoint (meta#8663) with the snap points, the
release position and velocity, flickThreshold and the drag's start,
instead of a release rule of its own: the nearest snap point, the next
one past the flick speed, and back to where the drag started when the
release moves back toward it (spec:AST-094 FR37). Its own
snapPointAfterRelease and nearestIndex are gone; the starting snap point
comes from the same policy. The pure-rule tests now check FR2's and
FR37's cases through that call, and the touch tests are unchanged.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This looks ready to approve: resolveSnapPoint stays internal, its projection and moving-back cancel follow AST-094 FR3 and FR37 with thresholds left to callers (AST-100 FR3), and selectPage keeps its exact behavior after the move. Nothing is required; one optional hardening before a public caller such as #8658 passes thresholds through: a still release with flickThreshold: 0 is treated as a downward flick, which a velocity !== 0 guard on the flick branch (as the cancel branch already has) would prevent.

[Automated review]

maxSteps,
});
let index = choice.index;
if (Math.abs(velocity) >= flickThreshold) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional hardening: with flickThreshold: 0, a still release (velocity === 0) enters this branch and the else arm walks down the axis, so resolveSnapPoint({points: [0, 300, 640], position: 300, velocity: 0, flickThreshold: 0}) returns index 0 instead of 1. A velocity !== 0 guard here, as the cancel branch below has, keeps a still release from flicking if a caller-supplied threshold ever reaches 0.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 27, 2026
@cixzhang
cixzhang merged commit 6aea9bd into main Oct 27, 2026
81 of 117 checks passed
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…) into meta#8068

The motion README's table takes main's rows (resolveSnapPoint.ts,
selectPage.ts) plus this PR's uikit/sheet.ts row. The sheet's rule still
calls selectSnapPoint, which meta#8663 keeps.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…xperimental touch exports

The motion README's Files table is the union: main's rows, with meta#8663's
resolveSnapPoint.ts and selectPage.ts, plus this branch's, in main's
order.

# Conflicts:
#	packages/core/src/motion/README.md
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
The motion README's Files table is the union: main's rows, with meta#8663's
resolveSnapPoint.ts and selectPage.ts, plus this branch's, in main's
order.

# Conflicts:
#	packages/core/src/motion/README.md
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…; this pull request's presentation.ts rows kept beside them) into meta#8293
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…tor's browser proofs

The motion README's Files table is the union: main's rows, with meta#8663's
resolveSnapPoint.ts and selectPage.ts, plus this branch's, in main's
order.

# Conflicts:
#	packages/core/src/motion/README.md
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…licy) into the animator's presentation start
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…eta#8663) into uikit/c02-switch-touch, through c02-8124-base
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
meta#8627's dependencies in one commit, so its compare link shows only its own change: meta#8298 (the presentation resolver) and meta#8076 at 3fb31dd, which carries main's meta#8663.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
The base: the determinate fill on the compositor (meta#8196 de43cd2) and the touch foundation (meta#8076, with main through meta#8663).
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…for main's meta#8663 README conflict) into the keyboard clearance
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…eta#8663; the gesture-free test pins the utils entry only) into the AlertDialog tracking base
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…policy

Main now has one release policy, `motion/resolveSnapPoint.ts` (meta#8663):
"the one 'where does a release land' helper ... a component's release
rule calls it with its own points and thresholds". `paging.ts`'s own
`selectPage` was a second one, so it goes: the pager (meta#8146) picks the
page with these measured thresholds through `resolveSnapPoint`. The
thresholds stay in the paging table (`paging.release`), and their
measured page-choice tests move with the rule.

The scroll table keeps its `scroll.paging` estimates: main's
`motion/selectPage.ts` reads `scroll.paging.projectionRate`.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
`pageForRelease` is the pager's release rule on main's release policy,
`motion/resolveSnapPoint.ts` (meta#8663), with UIKit's measured paging
thresholds from `paging.release`: a flick from the advance speed on, the
nearest page below it, a release moving back toward the start page
settling there (spec:AST-094 FR37) through `start`, and at most one page
from the start page through `maxSteps`. A looping pager passes only the
pages within reach of its start page, so the target may leave the range
and the owner wraps it. The measured page-choice tests move here from
paging.test.ts.

One test released at exactly half a page: past the pan's 10 pt claim its
"90 px" drag moved the content 80 px. The policy settles an exact tie on
the earlier page; UIKit's measured rule is "past half a page, the next
one", so the finger now moves 100 px and the content travels the 90 px
the test describes.
@github-actions
github-actions Bot deleted the feat/resolve-snap-point branch October 28, 2026 06:17

This branch was successfully deployed

1 active deployment
Preview — c85d0925 Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant