Skip to content

chore(core): Core's internal touch entry names, for Lab, the screen-edge pan, spring solver, motion resolver, UIKit navigation springs and focus helpers - #9696

Merged
cixzhang merged 2 commits into
meta:mainfrom
vjeux:navigation-stack-core-entries
Nov 5, 2026

Conversation

@vjeux

@vjeux vjeux commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Stack: #9696 → #9697

The Core part of NavigationStack, split out so the Lab pull request that follows touches no Core file.

Maintainer impact

Lab's NavigationStack (the Lab pull request that follows) reads Core's screen-edge pan recognizer, spring solver and motion resolver, UIKit's navigation table and four navigation springs, and Core's focus helpers that follow the last input. Lab reaches Core modules outside the public API only through Core's internal entries, so @astryxdesign/core/internal/touch names them. The back button's fallback name needs one catalog key.

Intended invariant

No behavior change. The entry gains named re-exports only: no new module, no gathering object, no root re-export, no docs. Internal entries stay outside the public API and its compatibility promise, and the lint boundary allows them in Core and Lab only.

Authority: architecture:react-component-runtime INV13 (the internal entry, its lint boundary, and the Lab needs it serves), spec:AST-017 FR21, architecture:component-style-authoring INV6, spec:AST-094 FR19 and FR24 (nothing attaches on import), and architecture:internationalization INV6 (the catalog key).

Change

  • packages/core/src/internal/touch.ts re-exports ScreenEdgePanGestureRecognizer, resolveMotion, solveSpring, toSpring, navigation, the four rows NavigationStack plays (NAVIGATION_PUSH_SPRING, NAVIGATION_POP_SPRING, NAVIGATION_INTERACTIVE_POP_FINISH_SPRING, NAVIGATION_BAR_ELEMENTS_SPRING, not the whole springs table), focusForLastInput, isFocusLost and useInteractionModalityTracking, with the type SpringDescription. None is a public factory's name.
  • scripts/touch-support-bundle.test.mjs lists the twelve runtime names among those only Lab reads, so its check proves each is in the internal entry and not in the root entry.
  • packages/core/locales/en.json gains @astryx.navigationStack.back ("Back"), as the Comments family's Lab keys are.
  • A core changeset that names the entry as internal.

Evidence

  • Failure before the change: the new identity checks in touch.test.ts fail against main's entry, which lacks the names (expected undefined to be [Function: ScreenEdgePanGestureRecognizer]).
  • Success after the change: touch.test.ts and the touch-support bundle test pass; check:i18n-catalog and check:i18n-runtime pass with the new key.
  • Product/runtime behavior verified unchanged: re-exports only; no Core module imports the entry, and importing it still attaches no listeners.

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 (66e6c3b, on main 9e559e9), after a frozen install (exit 0): the internal-entry units 20/20 (5 files); the touch-support bundle test 11/11; Core typecheck exit 0; strict lint clean on the changed files; Prettier clean; check:i18n-catalog, check:i18n-runtime, check:changesets, changeset coverage, check:knowledge and check:repo pass; pnpm review:pre reports no findings (97 authored lines). Red-first on a committed arm, main's entry under this head's tests (e239256, not for landing): the entry test fails (expected undefined to be [Function: ScreenEdgePanGestureRecognizer]), and so does the bundle test's Lab-names check (expected [ …(12) ] to deeply equal []); at this head both pass.

@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 5, 2026 8:02pm 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
Contributor

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 5, 2026, 8:08 PM UTC

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · e3168e3

Storybook · Sandbox · built from this PR's head

Package size: measured; main has no measurement of the merge base to compare yet.

API changes: cli +14 · ~5 · −0 (against the merge base's committed report)

Committed API report behind this build: cli 19 rows, core 23 rows; run pnpm api:report.

19 API changes (advisory)
Package Where Signature Usage
+ cli ./api · Types · type SearchResultEntry deprecated?: ComponentDeprecation | undefined import type {SearchResultEntry} from '@astryxdesign/cli/api'; const x: SearchResultEntry = {deprecated: …}
+ cli ./authoring · Types · interface ComponentDeprecation interface ComponentDeprecation import type {ComponentDeprecation} from '@astryxdesign/cli/authoring'
+ cli ./authoring · Types · interface ComponentIconSlotDoc interface ComponentIconSlotDoc import type {ComponentIconSlotDoc} from '@astryxdesign/cli/authoring'
+ cli ./authoring · Types · interface ComponentIconSlotStateDoc interface ComponentIconSlotStateDoc import type {ComponentIconSlotStateDoc} from '@astryxdesign/cli/authoring'
+ cli ./authoring · Types · interface MultiComponentDoc deprecated?: ComponentDeprecation import type {MultiComponentDoc} from '@astryxdesign/cli/authoring'; const x: MultiComponentDoc = {deprecated: …}
+ cli ./authoring · Types · interface SingleComponentDoc deprecated?: ComponentDeprecation import type {SingleComponentDoc} from '@astryxdesign/cli/authoring'; const x: SingleComponentDoc = {deprecated: …}
+ cli ./doc · Types · interface ComponentBaseDoc deprecated?: ComponentDeprecation import type {ComponentBaseDoc} from '@astryxdesign/cli/doc'; const x: ComponentBaseDoc = {deprecated: …}
+ cli ./doc · Types · interface SubComponentDoc deprecated?: ComponentDeprecation import type {SubComponentDoc} from '@astryxdesign/cli/doc'; const x: SubComponentDoc = {deprecated: …}
+ cli ./doc · Also exported from an earlier entry point · ComponentDeprecation ComponentDeprecation (./authoring) import {ComponentDeprecation} from '@astryxdesign/cli/doc'
+ cli ./doc · Also exported from an earlier entry point · ComponentIconSlotDoc ComponentIconSlotDoc (./authoring) import {ComponentIconSlotDoc} from '@astryxdesign/cli/doc'
+ cli ./doc · Also exported from an earlier entry point · ComponentIconSlotStateDoc ComponentIconSlotStateDoc (./authoring) import {ComponentIconSlotStateDoc} from '@astryxdesign/cli/doc'
+ cli ./template · Also exported from an earlier entry point · ComponentDeprecation ComponentDeprecation (./authoring) import {ComponentDeprecation} from '@astryxdesign/cli/template'
+ cli ./template · Also exported from an earlier entry point · ComponentIconSlotDoc ComponentIconSlotDoc (./authoring) import {ComponentIconSlotDoc} from '@astryxdesign/cli/template'
+ cli ./template · Also exported from an earlier entry point · ComponentIconSlotStateDoc ComponentIconSlotStateDoc (./authoring) import {ComponentIconSlotStateDoc} from '@astryxdesign/cli/template'
~ cli ./api · Functions · function search function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "hook" | "theme" | "doc" | undefined; limit?: number | undefined }) => Promise<SearchResponse> → function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "doc" | "theme" | "hook" | undefined; limit?: number | undefined }) => Promise<SearchResponse> import {search} from '@astryxdesign/cli/api'; search(…)
~ cli ./authoring · Types · interface MultiComponentDoc theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } import type {MultiComponentDoc} from '@astryxdesign/cli/authoring'; const x: MultiComponentDoc = {theming: …}
~ cli ./authoring · Types · interface SingleComponentDoc theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } import type {SingleComponentDoc} from '@astryxdesign/cli/authoring'; const x: SingleComponentDoc = {theming: …}
~ cli ./doc · Types · interface ComponentBaseDoc theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } import type {ComponentBaseDoc} from '@astryxdesign/cli/doc'; const x: ComponentBaseDoc = {theming: …}
~ cli ./doc · Types · interface SubComponentDoc theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } import type {SubComponentDoc} from '@astryxdesign/cli/doc'; const x: SubComponentDoc = {theming: …}

Not run on this PR: add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.


Generated by PR Enrichment workflow | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This needs an engineering owner's decision before it can be approved, plus three fixes.

Because the branch is stacked on #9399, the diff includes Lab's SearchField, which has no governing spec, and the pull request also changes Core, so the Lab exemption does not apply. An engineering owner records the decision on SearchField's direction as it stands (its stacked, bottom and tab placements, its motion, and its placement, lift, isActive and handleRef API) by commenting /approve-spec <full head SHA> on this pull request, or asks for its own spec first; the author may do so if they are an engineering owner.

Blocking:

  • SearchFieldTouch.ts adds its own document-level swallower for a claimed tap's late mouse events beside Core's shared click guard; extend the guard to drop the late mousedown/mouseup and remove the local copy.
  • The NavigationStack changeset says Lab's NavigationStack reaches these names, but no NavigationStack exists at this head; describe what the internal entry and the catalog gain instead.
  • The bottom and tab placements' keyboard behaviour needs iOS Simulator evidence recorded from this code, which the mobile keyboard spec requires before keyboard work merges.

The Core re-exports and the catalog key match the existing spec, and the new entry test proves them.

[Automated review]

// lets go (its click, the next press, or its window), the late events are
// over, and this swallow lets go too.
const disarmRef = useRef<(() => void) | null>(null);
const armSwallow = useCallback((doc: Document) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Blocking: this adds a second swallower for a claimed tap's late mouse events beside Core's shared click guard (utils/clickGuard.ts), which the gesture host already arms at the claimed lift; its document listeners also stay after the press until the next input. Extend the click guard (or the host's claimed-lift path) to drop the late mousedown/mouseup under the same disarm rules, and delete armSwallow, disarmRef and the unmount Effect, so every claimed tap gets the fix.

'@astryxdesign/core': patch
---

[experimental] Lab's experimental NavigationStack reaches Core's pan and screen-edge pan recognizers, spring solver, rubber band, motion resolver, UIKit tables and coarse-pointer query through Core's internal `@astryxdesign/core/internal/touch` entry. That entry stays outside the public API and its compatibility promise. Its back button's fallback name joins Core's message catalog.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Blocking: no NavigationStack exists at this head, so this release note would describe a component the release may not contain. Suggested wording: "[experimental] Core's internal @astryxdesign/core/internal/touch entry also names the pan and screen-edge pan recognizers, spring solver, rubber band, motion resolver, UIKit navigation, springs and gesture tables and the coarse-pointer query, for Lab. The entry stays outside the public API and its compatibility promise. Core's English catalog gains @astryx.navigationStack.back."

Comment on lines +330 to +331
// Inactive, the close button is transparent (the animator holds its
// opacity at 0) and takes no taps.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: these two lines describe closeInert, which has its own comment below; here they sit above beforePlacement. Delete them.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This needs an engineering owner's decision on SearchField's direction before it can be approved, plus two fixes.

Because the branch is stacked on #9399, the diff includes Lab's SearchField, which has no governing spec, and the pull request also changes Core, so it is not a Lab-only change. An engineering owner records a decision on SearchField as it stands (its stacked, bottom and tab placements, its activation and cancel motion, the claimed tap at the bottom, and its placement, lift, isActive/onActiveChange and handleRef API) by commenting /approve-spec <full head SHA> on this pull request, or asks for a spec record first; the author may do so if they are an engineering owner.

Blocking:

  • The title says Lab's NavigationStack reaches Core's names, but no NavigationStack exists at this head, so retitle it to what the change does, for example "chore(core): Core's internal touch entry names the pan recognizers, spring solver, rubber band and UIKit tables for Lab".
  • spec:AST-099 DEC-3 makes iOS Simulator evidence in a top-level document a merge gate for keyboard work, and SearchField's only iOS evidence comes from the drafts this code replaced, so add an iOS Simulator run of the Bottom and InTabBar stories at this head.

SearchField's second late-click swallower is gone and the changeset no longer names NavigationStack.

[Automated review]


const storybook = withStorybook(test);

/** UIKit's search activation on iOS 26.2 (uikit/search.ts). */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: uikit/search.ts does not exist; the search table is packages/lab/src/internal/searchMotion.ts.

const storybook = withStorybook(test);

// The bottom placement's measurements, as in the UIKit table
// (`search.bottom`, motion/uikit/search.ts, which search.test.ts holds

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: motion/uikit/search.ts and search.test.ts do not exist; the table is packages/lab/src/internal/searchMotion.ts, checked by searchMotion.test.ts.

Comment on lines +449 to +450
// The field box hosts the leading end (::before) and the middle
// (::after); the trailing part hosts the trailing end's cap (::before).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: this restates the merged refs on the next line and the SearchFieldMotion JSDoc. Delete it.

Comment on lines +109 to +110
// The rounded ends and the middle are pseudo-elements, being decoration:
// the field's ::before and ::after, and the trailing part's ::before.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: this restates the pseudoElement options below. Delete it, or keep only: "The rounded ends and the middle are decoration, so they are pseudo-elements."

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested: two fixes before this can merge.

  • packages/core/src/internal/touch.ts:49 re-exports createAnimator as createMotionAnimator, but main already renamed that factory to createMotionAnimator (#8653), so once merged Core's typecheck fails, the entry's createMotionAnimator is undefined and useMotionAnimator throws; re-export createMotionAnimator directly, compare with animator.createMotionAnimator in touch.test.ts:44, and rebase on main.
  • The title says Lab's NavigationStack reaches these modules, but no NavigationStack exists in this pull request or on main; retitle it to what it does, for example "chore(core): Core's internal touch entry names the screen-edge pan recognizer, spring solver, rubber band inverse and UIKit navigation and springs tables for Lab".

The first fix belongs in #9754's commit, which this branch carries. The identity checks in touch.test.ts pass when both sides are undefined, so asserting that each entry name is defined would catch a rename like this one. Otherwise the new entry names, the internal hook and the catalog key fit the existing rules for internal entries and the English catalog.

[Automated review]

Comment thread packages/core/src/internal/touch.ts Outdated
export {isRtlElement} from '../hooks/isRtlElement';
// The animator's internal factory, under a name no public factory has: the
// public animator factory is `createAnimator`.
export {createAnimator as createMotionAnimator} from '../motion/animator';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Blocking: main already renamed this factory to createMotionAnimator (#8653), and this file merges without a conflict, so after the merge Core's typecheck reports TS2305 here and the entry's createMotionAnimator is undefined. Re-export it under its own name, export {createMotionAnimator} from '../motion/animator';, and delete the comment above, which then only restates the name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed by the re-pin onto #9754 (4e363d8), which re-exports the engine under its own name, now createMotionEngine; this pull request no longer touches that line. At 7723b7f it adds only its own names.

expect(entry.useGestureRecognizer).toBe(hook.useGestureRecognizer);
expect(entry.useTouchPresentation).toBe(presentation.useTouchPresentation);
expect(entry.isRtlElement).toBe(direction.isRtlElement);
expect(entry.createMotionAnimator).toBe(animator.createAnimator);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Blocking (same fix): on main both sides of this check are undefined, so it passes while the entry is broken. Compare with animator.createMotionAnimator, and assert that each entry name is defined so a rename on the module side fails here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed: the identity checks compare with the renamed export, and every name this pull request adds also sits in the base's defined-checks (typeof … === 'function' or toBeDefined), so a rename on the module side fails here.

@vjeux
vjeux force-pushed the navigation-stack-core-entries branch from 570f836 to 7723b7f Compare November 3, 2026 15:15
@vjeux vjeux changed the title chore(core): Lab's NavigationStack reaches Core's pan recognizers, spring solver, rubber band and UIKit tables chore(core): Core's internal touch entry names the screen-edge pan recognizer, spring solver, motion resolver, rubber band inverse and UIKit navigation and springs tables for Lab Nov 3, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested: one fix before this can merge.

  • .changeset/core-internal-entries-lab-navigationstack.md files this internal-entry change as [experimental], so Core's changelog would list it under "Experimental APIs" although the entry stays outside the public API; file it as [chore] Internal: …, as #9754's changeset for the same entry already does.

The earlier alias break and title are fixed: the entry re-exports createMotionEngine directly, the identity checks also assert that each name is defined, and the title names only what the entry adds. Two optional comment fixes are inline.

[Automated review]

'@astryxdesign/core': patch
---

[experimental] Core's internal `@astryxdesign/core/internal/touch` entry also names, for Lab, the screen-edge pan recognizer, the spring solver, the rubber band's inverse and the motion resolver. It also names UIKit's navigation and springs tables. The entry stays outside the public API and its compatibility promise. Core's English catalog gains `@astryx.navigationStack.back`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Blocking: [experimental] puts this note under "Experimental APIs" in Core's changelog, but the internal entry is outside the public API and carries no experimental surface. Suggested, matching #9754's changeset:

[chore] Internal: Core's internal touch entry also names, for Lab, the screen-edge pan recognizer, the spring solver, the rubber band's inverse and the motion resolver, and UIKit's navigation and springs tables. Core's English catalog gains `@astryx.navigationStack.back`. Apps import nothing new.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done at c8a5d47: the changeset is now [chore] Internal: …, word for word as suggested, matching #9754's.

Comment thread packages/core/src/internal/touch.ts Outdated
Comment on lines 7 to 8
* @output `@astryxdesign/core/internal/touch`: the gesture core's primitives
* for Lab components, re-exported by name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Optional: @input now names the motion, touch and direction modules, but @output still says "the gesture core's primitives". Suggested:

 * @output `@astryxdesign/core/internal/touch`: the gesture, motion,
 *   touch-presentation and direction modules Lab uses, re-exported by name

Comment thread packages/core/src/motion/animator.ts Outdated

/**
* Options of `createMotionAnimator`.
* Options of `createMotionEngine`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Optional: this comment sits above SetOptions' own comment and documents nothing. Move it above export interface AnimatorOptions, which the internal entry now re-exports as MotionEngineOptions, or delete it.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No blocking findings: every change stays inside Core's internal touch entry, Core's English catalog and Lab's internals, each matches the current records, and the changeset is now filed as [chore] Internal:.

Two optional comment fixes:

  • packages/core/src/internal/touch.ts:7-8: @output still says "the gesture core's primitives", but the entry now also re-exports motion, touch-presentation and direction modules.
  • packages/core/src/motion/animator.ts:300-302: "Options of createMotionEngine." sits above SetOptions and documents nothing; move it above AnimatorOptions or delete it.

[Automated review]

@vjeux
vjeux force-pushed the navigation-stack-core-entries branch from c8a5d47 to 96b09a8 Compare November 5, 2026 14:04
@vjeux vjeux changed the title chore(core): Core's internal touch entry names the screen-edge pan recognizer, spring solver, motion resolver, rubber band inverse and UIKit navigation and springs tables for Lab chore(core): Core's internal touch entry names the screen-edge pan recognizer, spring solver, motion resolver and UIKit navigation and springs tables for Lab Nov 5, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested: one fix before this can merge.

  • Miss: packages/core/src/internal/touch.ts:90 re-exports the whole 35-row springs table for Lab's NavigationStack, so that component's import would carry spring rows only other components read, against architecture:component-style-authoring INV6; re-export the four rows it plays (NAVIGATION_PUSH_SPRING, NAVIGATION_POP_SPRING, NAVIGATION_INTERACTIVE_POP_FINISH_SPRING, NAVIGATION_BAR_ELEMENTS_SPRING) in place of springs, and update touch.test.ts and LAB_ONLY_NAMES to match.

The other names stay inside Core's internal entry as spec:AST-017 FR21 and architecture:react-component-runtime INV13 allow, and the catalog key follows the English source contract. #9697 does not yet carry the same Stack: line or sit on this head, so this pull request was reviewed on its own.

[Automated review]

Comment thread packages/core/src/internal/touch.ts Outdated
export {solveSpring, toSpring} from '../motion/spring';
export type {SpringDescription} from '../motion/spring';
export {navigation, registerNavigationTable} from '../motion/uikit/navigation';
export {registerSpringsTable, springs} from '../motion/uikit/springs';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Miss (blocking): springs is the table of all 35 UIKit spring rows, so a Lab component that reads it through this entry carries the sheet, alert, keyboard, banner and switch rows too, against architecture:component-style-authoring INV6 ("ships to a component only the rows that component uses"). Re-export the rows NavigationStack plays instead:

export {
  NAVIGATION_BAR_ELEMENTS_SPRING,
  NAVIGATION_INTERACTIVE_POP_FINISH_SPRING,
  NAVIGATION_POP_SPRING,
  NAVIGATION_PUSH_SPRING,
  registerSpringsTable,
} from '../motion/uikit/springs';

Then update touch.test.ts and LAB_ONLY_NAMES in scripts/touch-support-bundle.test.mjs to match.

Lab's NavigationStack, which follows in its own pull request, reads the
screen-edge pan recognizer, the spring solver, the motion resolver,
UIKit's navigation table and its four navigation springs. It also reads
Core's focus helpers that follow the last input. Core's internal
`@astryxdesign/core/internal/touch` entry now names them: named
re-exports only, outside the public API. The entry test checks each
runtime name is the value Core imports by path. The touch-support bundle
test checks each is in the internal entry and not in the root entry.

The stack's back button falls back to one catalog key,
`@astryx.navigationStack.back`, added to Core's English catalog as the
Comments family's Lab keys are.
@vjeux vjeux changed the title chore(core): Core's internal touch entry names the screen-edge pan recognizer, spring solver, motion resolver and UIKit navigation and springs tables for Lab chore(core): Core's internal touch entry names, for Lab, the screen-edge pan, spring solver, motion resolver, UIKit navigation springs and focus helpers Nov 5, 2026
@vjeux
vjeux force-pushed the navigation-stack-core-entries branch from 96b09a8 to 66e6c3b Compare November 5, 2026 15:12

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

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. It runs once the pull request leaves draft and, because the branch is in a fork, a maintainer adds the ci:run label.

Every new name stays inside Core's internal touch entry, which now re-exports the four navigation spring rows instead of the whole springs table, and the new key follows the English catalog contract. The new tests fail against main's entry and pass here.

  • #9697 does not yet carry the same Stack: line and is not based on this head: it still imports springs, registerNavigationTable and registerSpringsTable, which this head no longer exports, so it needs a rebase onto this head before the two can land.

[Automated review]

@cixzhang

cixzhang commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 66e6c3b

@vjeux
vjeux marked this pull request as ready for review November 5, 2026 15:58
@cixzhang cixzhang added the ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) label Nov 5, 2026
@cixzhang
cixzhang marked this pull request as draft November 5, 2026 16:52
@cixzhang
cixzhang marked this pull request as ready for review November 5, 2026 16:52
@cixzhang

cixzhang commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

/approve-spec e3168e3

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

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 finished on this head yet.

Every new name stays inside Core's internal touch entry, with only the four navigation spring rows rather than the whole springs table, and the new English key follows the catalog contract. The new tests fail against main's entry and pass here, and the merge from main leaves the pull request's own change as it was.

  • #9697 still sits on this branch's commit from before main was merged in; rebasing it onto this head keeps the declared stack consistent.

[Automated review]

@cixzhang
cixzhang merged commit 5393266 into meta:main Nov 5, 2026
67 checks passed
@vjeux
vjeux deleted the navigation-stack-core-entries branch November 5, 2026 22:42

This branch was successfully deployed

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

Labels

ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) 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