Skip to content

chore(core): the press controller leaves an action group's tracked actions to its tracker - #8637

Closed
vjeux wants to merge 1631 commits into
meta:mainfrom
vjeux:uikit/c01-press-group-skip
Closed

vjeux wants to merge 1631 commits into
meta:mainfrom
vjeux:uikit/c01-press-group-skip

Conversation

@vjeux

@vjeux vjeux commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review this PR alone: vjeux/astryx@uikit/f2-click-guard...uikit/c01-press-group-skip

Maintainer impact

Part of the UIKit-parity work: in a group of sibling actions (an alert's buttons, a button group, a toggle group) you can press one and slide to another, as on iOS (family:action-groups, from #8622). The group's own tracker paints the press on the action under the pointer. The page-wide press controller paints the same buttons, so the two erase each other: the controller's release fade wipes the group's highlight, and the button you started on stays lit beside the one you slid to.

Intended invariant

One painter per press. The controller already calls itself the one writer of the press attribute; a group takes that role only for the actions it tracks.

Change

What led to it: building the group tracking for AlertDialog and ButtonGroup showed the double paint.

  • Skip every element inside a tracking group: rejected, it would also silence members the group doesn't track, such as a field or a split button's menu trigger.
  • Chosen: the group marks each action it tracks (data-astryx-press-group-item), and the controller paints nothing on a marked action. The mark is there before the first press, and the group can use the same attribute to find its actions.

The controller still records the touch on a marked action, so a scroll it starts still brakes the next touch. Where the primary pointer is coarse the controller also paints a mouse press itself (#8046); on a marked action it leaves that to the group too, while a Space press, which the group doesn't track, still paints. No component renders the marker yet: nothing changes until each group adopts it (#8083, #8657, #8660).

Evidence

  • packages/core/src/utils/pressFeedback.test.ts, six new cases (below).

Scope

  • No intended public API, product behavior, visual direction, or policy change. utils/pressFeedback.ts is internal: it is not on a published entry point.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

Nothing to check by hand yet: no component carries the marker.

What was run: six new unit tests. The controller paints nothing on a marked action and leaves the group's paint alone, for a finger and for a mouse on a touch-first device; those fail without this change. It still paints an unmarked member, which fails if the skip checks group membership instead of the mark, and a Space press on a marked action. It still records the touch for the scroll brake, which fails if the skip comes first. Typecheck, lint, the core unit suite and the press accessibility tests pass locally; GitHub Actions isn't running on this repository right now.

Stack: on #8360, which carries #8076. The adoptions (#8083, #8657, #8660) stack on this pull request.

cixzhang and others added 30 commits October 26, 2026 14:00
startCompositorTrace keeps every Display::FrameDisplayed in the browser, and
those events carry no page identity: with a second page animating, a stall
inside the block passed busyWindowProof with presented, crediting the other
page's frames. It now throws when another page is open as it starts or
stops, and says the record is browser-wide (JSDoc and README). Negative
control: another animating page makes it refuse to start, and a page opened
mid-trace makes stop() refuse.
A bare relative ASTRYX_WEBKIT_SHADER_CACHE was mounted as a named volume
instead of a host directory, and an empty one made mkdirSync throw. The
script now resolves a set value with path.resolve and falls back to the
default cache directory on an empty one.
… path) into the recorder stand-down

# Conflicts:
#	internal/interaction-harness/src/harness.interaction.browser.spec.ts
…ce; await it before the counted window

The README, waitForRest's JSDoc and traceRendering's JSDoc said a traced
waitForRest reads no style. Its one read of the element's animations, as it
is called, restyles the element when an animation is already running there
(2 Layouts and 2 style recalculations in the anchored fixture, 200 ms into
its animation). They now say so and tell a proof to await it right after
the action that starts the motion, before the window it counts.
…ch-action rules in @layer reset, the watcher split into meta#8589) into meta#8293
Under Reduce Motion, detaching mid-dip landed the waiting move in the model
at the end of the task, but with no element attached the landing wrote
nothing, so a call that owns its opacity left its dip's low opacity inline
on that node: attaching the same node again in a later task (a Suspense or
Activity reveal) showed it at opacity 0. The unmount's landing now writes to
the node just detached, as dispose() does to its element. The test fails
on the previous head.

(Found on meta#8067; fixed here because meta#8056, which carries the planner, is
approved at its exact head.)
… against its span

In WebKit the rAF negative control could read "1/1 moved": one frame from
before the block arrived 45 ms into it, and the moved criterion divided by
the delivered frames. A part that delivered fewer than minJudgedFrames
frames is now judged against its span, as one that delivered none was
(busy.test.ts case; it fails on the previous rule). The README and the
self-test header now say only the busy-main-thread proof carries a negative
control beside its positive check.
…into n8548

# Conflicts:
#	internal/interaction-harness/README.md
The lock moved to utils/selectionLock.ts with the shared input stream, and
stacks based below that move import it from gestures/selectionLock.ts; a
tree carrying both failed to typecheck. The case imports the old path and
expects the utils module's functions. Fails on this head.
…rom utils

A one-line transition re-export at gestures/selectionLock.ts keeps
`import {lockSelection} from '../gestures/selectionLock'` working for the
stacks based below the move to utils, so a tree that carries both
typechecks. Remove it once they have moved up.
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>
…l, straight or diagonal, and not before

spec:AST-094 FR20's verification names a finger moved 9 px and 10 px
straight, and (7, 7) and (8, 8) diagonally: a scroll above the touch takes
it only once the finger has travelled 10 px from where it landed. The host
already measures that distance; these cases pin the boundary.
…g running

Landing a waiting Reduce Motion move on the node just detached rebuilt
every channel the landing touched there, so an axis still moving (a coast
on y while x waited in a dip) was baked onto the detached node again and
promoted it, leaving an animation, timers and will-change behind. After the
landing, the unmount now cancels what runs, clears the retire timers and
demotes, before the target goes back to none. The test fails on the
previous head.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…'s tracked actions to its tracker) onto F2's line (meta#8360 777ff9a)

Conflicts, doc text only, in utils/pressFeedback.ts and its test: the
header keeps the line's selection-lock and touchcancel paragraphs, then the
group-item paragraph, and lists the group-item exports; the test imports
both sides' names.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
The document press controller painted AlertDialog's actions on its own
clock beside the group's tracker, so AlertDialog took them off the
controller by overriding Button's pressable marker, which also took them
off the scroll brake. Each tracked action now renders the shared group item
marker (`pressGroupItemProps`, meta#8637) from its first render: the controller
leaves a pointer's press there to the tracker, the one painter, and still
records the touch. The marker is also the tracker's item selector, so the
actions are named once. The inline preview is not tracked and keeps the
controller's press.

The selection lock is imported from utils/selectionLock, its home since
meta#8356; the gestures path is a transition re-export.

The unit case checks both markers on the open alert (fails on the previous
head: no group item marker) and neither group marker in the inline preview.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…01's meta#8637 helper) into meta#8084

# Conflicts:
#	packages/core/src/AlertDialog/AlertDialog.test.tsx
#	packages/core/src/AlertDialog/AlertDialog.tsx
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…01's meta#8637 helper) into meta#8095

# Conflicts:
#	packages/core/src/AlertDialog/AlertDialog.tsx
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…'s tracked actions to its tracker) onto F2's line (meta#8360 df700c4)

Conflicts, doc text only, in utils/pressFeedback.ts and its test: the
header keeps the line's selection-lock and touchcancel paragraphs, then the
group-item paragraph, and lists the group-item exports; the test imports
both sides' names.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…'s tracked actions to its tracker) onto F2's fZ (meta#8360 23ade34)

Conflicts, doc text only, in utils/pressFeedback.ts and its test: the
header keeps the line's selection-lock and touchcancel paragraphs, then the
group-item paragraph, and lists the group-item exports; the test imports
both sides' names.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
@vjeux
vjeux force-pushed the uikit/c01-press-group-skip branch from ed3d750 to 071ae26 Compare November 3, 2026 22:59

@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: the press-group marker this pull request adds is already on main, so the branch needs a rebase that will most likely leave nothing to land.

  • main already owns the marker in privateAttributes/pressGroupItem.stylex.ts (from #8083 and #9771), and this branch's copy in utils/pressFeedback.ts conflicts with main in all three of its own files.
  • The mouse skip in buttonSurfaceAt (pressFeedback.ts:480-482, pinned by pressFeedback.test.ts:600-608) leaves a mouse press on a marked action unpainted where the primary pointer is coarse, against family:action-groups FR1 and FR5, which keep the group's tracker to a finger and a pen.
  • The diff carries 26,918 authored lines, 26,783 of them the #8360/#8076 stack, with no size exemption, and that stack has since landed on main.
  • The carried stack contradicts current spec in places main has already fixed: GestureHost attaches only under a coarse primary pointer (AST-094 FR19/FR43, react-component-runtime INV13), PressTracker is a class (INV13), a DropdownMenu trigger keeps 10 px of drift on a fine primary pointer (useMenuPress FR9), and useFingerScroll copies useAttachment instead of calling it.

Rebase onto main, keep only what main lacks, and close the pull request if nothing remains.

[Automated review]

@@ -344,6 +475,11 @@ function buttonSurfaceAt(
if (pointerId == null && element !== target) {
return null;
}
// A group's tracker paints a pointer's press on its actions, a mouse's too;
// a key's press is the action's own.
if (pointerId != null && trackedByGroup(element)) {

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.

On a phone or tablet this leaves a mouse press on a marked action unpainted: :active is dropped there, and under family:action-groups FR1 and FR5 no group tracker follows a mouse. main has the mark name the pointers its tracker follows (pressGroupItemProps(['touch', 'pen'])) and skips only those.

* it, and the controller paints none there. The owner renders it on each
* action its tracker follows, so it is in place before the first press.
*/
export const PRESS_GROUP_ITEM_ATTRIBUTE = 'data-astryx-press-group-item';

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.

main already owns this attribute in privateAttributes/pressGroupItem.stylex.ts (from #8083 and #9771), and this file conflicts with main. A rebase should drop this copy and use that module.

@vjeux

vjeux commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Closing: main already has this change (the group-item marker via #8083, and the card-45 mouse rule via #9771).

@vjeux vjeux closed this Nov 3, 2026
@vjeux
vjeux deleted the uikit/c01-press-group-skip branch November 3, 2026 23:28
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…ions to its tracker

meta#8637's own change. A press on an action a group tracks (the group item
marker) is the group's tracker's to paint, for a finger and, on a
touch-first device, for a mouse too; the controller paints nothing there.

Absorbs meta#8637 (ed3d750).
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…ions to its tracker

meta#8637's own change. A press on an action a group tracks (the group item
marker) is the group's tracker's to paint, for a finger and, on a
touch-first device, for a mouse too; the controller paints nothing there.

Absorbs meta#8637 (ed3d750).
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…ions to its tracker

meta#8637's own change. A press on an action a group tracks (the group item
marker) is the group's tracker's to paint, for a finger and, on a
touch-first device, for a mouse too; the controller paints nothing there.

Absorbs meta#8637 (ed3d750).
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
…ions to its tracker

meta#8637's own change. A press on an action a group tracks (the group item
marker) is the group's tracker's to paint, for a finger and, on a
touch-first device, for a mouse too; the controller paints nothing there.

Absorbs meta#8637 (ed3d750).
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 3, 2026

This branch was successfully deployed

1 active deployment
Preview — 071ae261 Deployed Nov 3, 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. needs:design-review Affects visuals — Design should review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants