Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
3bd3483 to
190b6a1
Compare
190b6a1 to
7f6b9ab
Compare
There was a problem hiding this comment.
Approval waits on an engineering owner's decision about the draft spec:AST-094 (touch presentations follow UIKit): its FR1–FR23 and DEC-1/DEC-2 are new requirements that no current record states, yet they are the only authority for this branch's AlertDialog touch tracking and motion and for the new 744px/500px bottom-sheet rule, so an engineering owner needs to approve or reject them by commenting /approve-spec <full head SHA> on this pull request (the author, as an engineering owner, may do so). That decision also needs to cover the record's proposed amendments to architecture:theme-tokens INV3, design:user-states DR1 and DR3, the family:buttons press treatment and spec:AST-025 FR14. Separately, because the PR targets main, its diff is the whole 26-commit stack (about 27,000 lines in 144 files) rather than the four-file tracker refactor the description covers; please retarget it onto #8084's branch or rebase it once the stack has landed. The tracker extraction itself reads as behavior-preserving.
[Automated review]
PR Analysis Report
View Storybook for this PR · View Sandbox for this PR Generated by PR Enrichment workflow | View current CI run |
7f6b9ab to
230fe23
Compare
There was a problem hiding this comment.
Approval waits on an engineering owner's decision about the draft spec:AST-094 (touch presentations follow UIKit): its FR1–FR23 and DEC-1/DEC-2 are new requirements that no current record states, yet they are the only authority for this branch's AlertDialog touch tracking and motion and for the new 744px/500px sheet rule, which also departs from Selector's current DEC-1 ("adaptive keeps its width-and-pointer query"). An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request (the author may do so as an engineering owner), and the description needs the ## Writing rubric results for the record that the review gate reads such an approval against. Separately, because the PR targets main, its diff is the whole 28-commit stack (about 28,000 lines in 145 files) rather than the four-file tracker refactor the description covers, so please retarget it onto #8084's branch or rebase it once the stack has landed. Seven [chore] changesets (for example gesture-host.md and uikit-motion-animator.md) still say no component uses code that AlertDialog now runs, so please reword them before they publish.
[Automated review]
| export const COMPACT_TOUCH_QUERY = | ||
| '(width < 744px) and (pointer: coarse), (height < 500px) and (pointer: coarse)'; |
There was a problem hiding this comment.
This query changes what presentation="adaptive" resolves to for DropdownMenu, ContextMenu, MoreMenu, Selector and MultiSelector, and where DropdownMenu and ContextMenu sub-menus drill in (useMenuDrillIn.tsx reads the same constant): a phone in landscape now gets the sheet, and a 744 to 768 px wide touch screen the anchored popover. Selector's current record says in DEC-1 that adaptive keeps its width-and-pointer query, so this rule needs an engineering owner's decision alongside the draft AST-094 FR13.
There was a problem hiding this comment.
That query belongs to the touch presentation resolver (#8062); the decision is with its owners.
| '@astryxdesign/core': patch | ||
| --- | ||
|
|
||
| [chore] Internal: the gesture system's DOM host (claims, click suppression, the browser's takeover, the pointer behind a contact). Not exported from the package entry point; no component uses it yet. |
There was a problem hiding this comment.
At this head AlertDialog runs the gesture host (through useGestureRecognizer), so "no component uses it yet" will be false in the release that ships alertdialog-touch-action-tracking.md. The same sentence appears in gesture-recognizer-core.md, gesture-tap-long-press.md, gesture-browser-negotiation.md, uikit-motion-animator.md and uikit-motion-math.md, and as "no component reads it yet" in uikit-constants-table.md; dropping it, or naming AlertDialog as the first consumer, keeps the changelog accurate.
There was a problem hiding this comment.
Those [chore] changesets belong to the foundation PRs; the wording is with their owners.
|
Posted by Cindy's agent on her behalf. Parts of this PR re-implement behavior that already exists, or is being specified, as a shared part of core. Converging keeps one implementation per behavior:
This is about where the behavior lives, not about the PR's intent. |
|
Agreed: one implementation.
|
230fe23 to
70c9abd
Compare
A watcher already adds nothing to the derived touch-action, and manageStyle is per element, so attaching one with manageStyle: false beside a claiming recognizer switched off that recognizer's touch-action (spec:AST-094 FR18). The README now says a watcher adds nothing instead. Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
…n roles springs.alertPresent and springs.alertDismiss spec:AST-094 FR4 has every spring a touch presentation plays be a motion role; the alert played its springs straight from the table. They are now registered as internal roles (DEC-11: no theme surface), named in FR4's role table with their measured values, and useAlertMotion plays them through the roles after registering the springs table. A new test checks the roles the alert plays and fails on the old constants. Co-authored-by: Christopher Chedeau <vjeux@users.noreply.github.com>
…acking turns off or the group unmounts The case "leaves no fade behind when tracking turns off or the group unmounts" asserted that no timer at all was left. F2's shared click guard on meta#8360 arms a window at each tracked release, and that window must outlive the closing alert so the lift's click is still swallowed; in a tree that carries it the case failed with one timer left (C19 folding meta#8110), though the fade itself was gone. Each check now counts the timers that go: the lift starts the fade's timer, and turning tracking off, or unmounting, removes exactly that one. A leaked fade still fails it (checked by removing the fade's clearTimeout: 1 timer left where none should be). Verified on this head and on a scratch merge with meta#8360 559ab88, where the old case fails (expected 1 to be 0) and this one passes, 21 of 21.
… and name the old and new defaults in the changeset - The alert's springs are the roles alert.present and alert.dismiss, in the alert's own motion table (motion/uikit/alert.ts), so registering them carries those two rows and no other spring (it registered the whole springs table before, +596 B gzip; architecture:component-style-authoring INV6). FR4's role table names them; a bundle test checks the rows. - The changeset names the defaults under a finger: the width goes from 400 to 320 px, and the motion replaces the Dialog's entrance (rising 16 px and scaling from 0.95 while it fades in) and exit (spec:AST-017 FR3). - useAlertMotion's header says its springs are internal roles. Co-authored-by: Christopher Chedeau <vjeux@users.noreply.github.com>
…, citing the animator's iOS Safari known limit Co-authored-by: Christopher Chedeau <vjeux@users.noreply.github.com>
|
Posted by Cindy's agent on her behalf. Cindy's decision on sliding between actions: a group of actions behaves like a menu under a press. Press an action, slide across its sibling actions with the highlight following, and the action you lift on runs. Sliding off the group cancels. One shared module, the existing action-group tracker, governs this for menus, SegmentedControl, AlertDialog's actions, Dialog's action/footer area (not arbitrary dialog content), ButtonGroup and ToggleButtonGroup. In a toggle group, only the item you lift on toggles; sliding across never toggles the items in between. Keyboard and screen-reader behavior is unchanged. The record amendment to |
There was a problem hiding this comment.
Approval waits on an engineering owner's decision: this head adds alert.present and alert.dismiss to spec:AST-094 FR4, which the record on main does not list, so an engineering owner needs to approve those two rows by commenting /approve-spec <full head SHA> on this pull request (the author may do so as an engineering owner), or have them named in AlertDialog's own record instead. Whatever that decision, these changes are still needed:
- Land #8084, #8346 and the #8360 gesture line first (or retarget onto the parent branch), so this pull request is its 182-line refactor rather than about 34,800 lines against
main. - Remove the Lab core-internal module resolver, or move it to the
@astryxdesign/core/internal/touchsubpath thatmain's react-component-runtime INV13 now prescribes. - Correct
gesture-browser-negotiation.mdandgesture-press-tracking.md, which say no component uses code that AlertDialog now runs. - Have the action-group tracker paint through
paintPress, which this diff declares the press attribute's only writer.
[Automated review]
| | `springs.menuClose` | damping ratio 0.85, response 0.35 s | measured: UIMenu closing, iOS 26.2 simulator, 2026-10-23 | | ||
| | `springs.subMenuOpen` | damping ratio 0.85, response 0.4 s | measured: UIKit's own spring for UIMenu's sub-menu opening, iOS 26.2 simulator, 2026-10-24 | | ||
| | `springs.subMenuBack` | damping ratio 1, response 0.4 s | measured: UIKit's own spring for UIMenu's sub-menu header back, iOS 26.2 simulator, 2026-10-24 | | ||
| | `alert.present` | mass 1, stiffness 522.35, damping 45.71 | measured: UIAlertController alert appearing, iOS 26.2 simulator, 2026-10-23 | |
There was a problem hiding this comment.
These two rows add AlertDialog's springs to FR4's role table, which AST-094 on main does not list; FR4 and DEC-5 there have a component's own measured roles join through the generated role table from that component's own record. They need an engineering owner's decision (/approve-spec <full head SHA>), or a move to AlertDialog's record.
| const path = require('node:path'); | ||
|
|
||
| /** The internal module paths Lab imports: motion, gestures, the touch resolver. */ | ||
| const CORE_INTERNAL_SPECIFIER = |
There was a problem hiding this comment.
main's react-component-runtime INV13 now says Core and Lab reach the touch modules through @astryxdesign/core/internal/touch. Resolving @astryxdesign/core/motion/*, gestures/* and utils/touchPresentation here (and in Lab's tsconfig paths) takes a different route, and no Lab source imports these paths yet, so this could go until the first Lab import needs the subpath.
| return; | ||
| } | ||
| clearFade(element); | ||
| element.setAttribute(PRESSED_ATTRIBUTE, 'on'); |
There was a problem hiding this comment.
This diff makes writePress/paintPress in utils/pressFeedback.ts the one writer of data-astryx-press (it keeps the fade clock and respects a held paint), but the tracker writes the attribute and runs its own fade timers here, at :251, :258-266 and in dispose. Painting through paintPress would keep a menu row's held paint intact once menus adopt the tracker.
meta#8220 keeps a phone menu beside its trigger (the engineering owner's decision), so the action sheet card's imports and exports no longer sit beside the covering placement's, and DropdownMenu imports the touch presentation read for the card itself (the covering placement imported it before). meta#8373 replaces meta#8110 as the base for the card's tracking and input hold.
|
Posted by Cindy's agent on her behalf: closed and reopened only to restart this PR's CI on the current workflow after tonight's queue-wide cancel; nothing in the PR changed. |
Depends on #8084, #8346, #8360. Review only this PR's change: vjeux/astryx@24627e8...b0106ad
Maintainer impact
useActionGroupTracking(#8083) tracks a group of actions the way UIKit does, but only for touches that begin on the element it is attached to: the gesture host (#8072) gives a recognizer only the touches that land inside it. Menus need the same tracking for a finger that went down elsewhere: the finger holding a DropdownMenu trigger slides into the menu that opened under it (UIMenu's handoff), and a context menu's long press continues into its menu. Without a shared core, each would re-implement the rect cache, paint and activation.Intended invariant
AlertDialog's tracking is unchanged, as #8083 and #8084 state it:
click()inside the lift's event;isInert()calls inert at begin is taken but paints and runs nothing;Change
The tracking moves from the hook into
actionGroupTracker.ts:createActionGroupTracker(getOptions)returnsbegin(x, y, {inert}),move,end,cancelandoffsetBy(dx, dy)(an autoscroll shifts the cached rects without reading layout) anddispose()(pending fades finish on unmount). Its options are severalroots,onHighlightChange, andpaintsHighlight: falsefor owners that show the highlight another way (a menu moves focus).useActionGroupTrackingbinds the tracker to its one long press exactly as before. A recognizer elsewhere drives the same object and must callendfrom its touchend.Evidence
useActionGroupTracking.test.tsxpasses unchanged; AlertDialog's suites pass unchanged; 13 new tracker tests drive it directly, including a press that begins while another is tracked.Scope
Testing
pnpm vitest runhooks, AlertDialog, ActionSheet, DropdownMenu, motion, gestures and utils at this head: 2435 passed, including the tracker's tests;useActionGroupTracking.test.tsxand AlertDialog's suites unchanged. Tracking turned off mid-touch runs the tracker'scancel(the held highlight drops, the lift runs nothing) and thendispose(pending fades end).pnpm buildandpnpm typecheck;CI=true pnpm lintwith no error; CLI experimental isolation and golden reads 47/47;check:knowledge,check:changesets.Stack (merge in this order): #8083 → #8084, #8346, and F2's line to #8360 → this PR.