Skip to content

chore(core): the motion and gesture internals that Lab's refresh pull reads - #9807

Draft
vjeux wants to merge 1 commit into
meta:mainfrom
vjeux:uikit/c28-rc-core
Draft

vjeux wants to merge 1 commit into
meta:mainfrom
vjeux:uikit/c28-rc-core

Conversation

@vjeux

@vjeux vjeux commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

RefreshControl's Core part, now only internal re-exports for vetting. Supersedes #8086. It lands right before its first user, Lab's pull to refresh (#9865).

Maintainer impact

Lab's useRefreshControl reads Core's pan recognizer, its hook and the motion engine through Core's internal touch entry. Lab may import Core only through Core's internal entries. This follows the precedent that Lab uses the internal motion engine with no public API.

Intended invariant

No behavior change in Core. The internal touch entry gains named re-exports of existing internals only: no gathering object, no root re-export, no docs. It stays outside the public API, and lint allows it only in Core and Lab.

Change

internal/touch.ts re-exports these, each an existing internal:

Symbol From Lab reads it for
PanGestureRecognizer, type PanGestureRecognizerOptions gestures/PanGestureRecognizer the pull's two pans
types GestureEventContext, GestureTouch, PointerKind gestures/types the pans' contacts
useGestureRecognizer gestures/useGestureRecognizer starting the pans
createMotionAnimator, SETTLE_THRESHOLD, types MotionAnimator, MotionAnimatorOptions, MotionCurve motion/animator motion a finger can catch: the pull, the settle and the end
cubicBezier motion/bezier the end's curve and the reveal
resolveMotion motion/resolveMotion the end's motion role, read as the animator reads roles
rubberBand, rubberBandInverse motion/rubberBand the pull's mapping
solveSpring, toSpring motion/spring the indicator's fade as a settle covers it
scroll motion/uikit/scroll the settle's bounce spring
registerTimingTable, timing motion/uikit/timing the end's curve

Not in it: the page's scroll-style claims, the scroll-lock subscription, the text-selection helpers and the touch presentation hook. UIRefreshControl's values live in Lab, and no locale key is added (the app supplies the announcement).

Evidence

  • Failure before the change: the new identity test in touch.test.ts fails against main's entry.
  • Success after the change: each re-export is the same value as its module's export. A bundle test builds the internal entry and the root entry with esbuild. All 13 names are in the first, and none is in the root, where Button is the control. The bundle test fails when the root entry exports one of them.
  • Product/runtime behavior verified unchanged: re-exports only; no Core module imports the entry.

Scope

  • No intended public API, product behavior, visual direction, or policy change.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

Local gates at this head, on main 47790d3: UI 787 files / 19,747 tests and node 883 files. The core type check and lint report 0 errors, and review:pre finds nothing.

Overlap: #9669, #9696 and #9699 add some of the same names to this entry; whichever merges later rebases and drops its duplicate lines.

@vercel

vercel Bot commented Nov 3, 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 Nov 4, 2026 8:34am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 3, 2026
@astracat-bot

astracat-bot Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 4, 2026, 8:41 AM UTC

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

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


Generated by PR Enrichment workflow | View current CI run

@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.

Changes requested for one fix in the table-imports guard. The internal-entry re-exports, the refreshControl table and the new catalog key match the current specs.

  • isInternalEntry in packages/core/src/motion/uikit/tableImports.test.ts (lines 60–62) exempts every .ts file under internal/, including indicatorPress.stylex.ts, sheetDraft.ts and useDismissSearchOnTouchDrag.ts, which CheckboxInput, TokenizerBottomSheet and PowerSearchBottomSheet import; please exempt only internal files no Core source imports (or internal/touch.ts alone) and correct the JSDoc that says no Core source imports one.

Optional: the comment at internal/touch.ts:45 can drop its first sentence, which restates the export list (suggestion inline). When RefreshControl leaves Lab, its springs, reveal curve and durations will need motion roles under the touch-presentations spec (FR4).

[Automated review]

Comment thread packages/core/src/internal/touch.ts Resolved

@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.

Ready to approve. The internal-entry re-exports, the refreshControl table and the new catalog key match the current specs, and the table-imports guard now exempts only internal files no Core source imports, which resolves the earlier comment on isInternalEntry.

  • Optional: the internal/touch.ts header is now 21 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (suggestion inline).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

* @input The gesture core: the arena, the recognizers, and their geometry;
* the motion math and UIKit tables that Lab's RefreshControl reads; the
* page's scroll-style claims
* @output `@astryxdesign/core/internal/touch`: the gesture core's primitives

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 (comment style): @output still describes only the gesture core's primitives, while the entry now also serves the motion math, UIKit tables, touch presentation hook and scroll-style claims, and the header is now 21 lines. Moving the new @input text here and keeping @input to what the file reads keeps the header accurate and shorter.

@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.

Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so once it is marked ready for review, a maintainer adds the ci:run label so CI runs.

The internal-entry re-exports, the refreshControl table and the new catalog key match the current specs, and the table-imports guard exempts only internal files that no Core source imports.

  • Optional: the internal/touch.ts header is 21 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (see the earlier inline suggestion).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

@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.

Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so once it is marked ready for review, a maintainer adds the ci:run label so CI runs.

The internal-entry re-exports (now including startsOnSelectableText), the refreshControl table and the new catalog key match the current specs, and the table-imports guard exempts only internal files that no Core source imports.

  • Optional: the internal/touch.ts header is 21 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (see the earlier inline suggestion).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

@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.

Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so once it is marked ready for review, a maintainer adds the ci:run label so CI runs.

The internal-entry re-exports (now including lockDragSelection and selectionRangesOf), the refreshControl table and the new catalog key match the current specs, and the table-imports guard exempts only internal files that no Core source imports.

  • Optional: the internal/touch.ts header is 22 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (see the earlier inline suggestion).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

… reads

Core's internal touch entry re-exports, by name, what Lab's
useRefreshControl reads: the pan recognizer, its hook and the gesture
types; the motion animator and its settle threshold; the cubic Bézier,
the motion resolver, the rubber band and its inverse, and the spring
solver; and the UIKit scroll and timing tables. Each one is an existing
internal, and Core's behavior does not change. A bundle test checks
that the public entry exports none of them.
@vjeux vjeux changed the title chore(core): what Lab's RefreshControl reads from Core, and UIRefreshControl's values chore(core): the motion and gesture internals that Lab's refresh pull reads Nov 4, 2026
@vjeux
vjeux force-pushed the uikit/c28-rc-core branch from 5a45b8d to 4a3074b Compare November 4, 2026 08:25
@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 4a3074b

@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.

Approved pending CI: CI has not run on this head yet. This is a draft from a fork, so a maintainer adds the ci:run label, and marking it ready for review then starts CI.

The new names on Core's internal touch entry match the current specs for internal subpaths, and the new tests show that none of them reaches the public entry.

  • Optional: two comments in packages/core/src/internal/touch.ts (lines 45–47 and 56–57) restate the exports or a name, and the header's @output still describes only the gesture core's primitives; suggestions are inline.

[Automated review]

Comment on lines +45 to +47
// Lab's useRefreshControl reads these: its pull's pan and the hook that
// starts it. It also reads the motion animator, math and UIKit tables of its
// pull, settle and end.

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 (comment style): after the colon, the comment lists the exports below it again. A version that keeps only the reason:

// Lab's useRefreshControl reads these.

Comment on lines +56 to +57
// The animator's internal factory. The public one, `createAnimator`, plays
// only the theme's state-change motion.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Miss: optional (comment style): "The animator's internal factory." restates the name createMotionAnimator. A version that keeps only the reason:

// The public `createAnimator` plays only the theme's state-change motion.

This branch was successfully deployed

1 active deployment
Preview — 4a3074bc Deployed Nov 4, 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.

2 participants