Skip to content

fix(gestures): a second finger fails a one-finger pan wherever fingers come from - #8336

Closed
vjeux wants to merge 1709 commits into
meta:mainfrom
vjeux:uikit/f2-host-line
Closed

vjeux wants to merge 1709 commits into
meta:mainfrom
vjeux:uikit/f2-host-line

Conversation

@vjeux

@vjeux vjeux commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Depends on #8665. Review only this pull request's change: vjeux/astryx@c6c02fc...283e7b2

Why

A one-finger pan, such as a swipeable row, could still claim a pinch where fingers reach the page as pointer events, so two fingers on the row moved it instead of zooming the page (WCAG 1.4.4). The same happened when a pinch's second finger landed on another one-finger pan. A press inside an open shadow root locked selection on the shadow host instead of what it touched.

What led to it

The host as the one document touch owner, which this pull request introduced, now rides in #8360, and the host attaches for every pointer in #8665, both of which merge first in the maintainer's order. These follow-ups from its review remain.

Options and tradeoffs

  • Check for a second finger only where Touch Events arrive: a page reading pointer events keeps the bug.
  • Check once, when the second finger lands: a finger the host learns of a moment later escapes the check.
  • Check wherever fingers come from, and again once the new finger is delivered.

Why this choice

The third keeps the page's pinch however fingers arrive: an unclaimed one-finger pan fails at a second finger, and the check reruns once that finger is delivered, so a pinch's second finger on another pan fails both (spec:AST-094 FR10). A press's selection lock takes what the press landed on, along the flat tree.

How to check it

  1. In a page reading pointer events, pinch with two fingers over a swipeable row. Expected: the page zooms, and the row does not move.
  2. Put the second finger of a pinch on a different swipeable row. Expected: neither row moves.
  3. Long-press text inside a web component's shadow root. Expected: the lock lands on that text's element.

Evidence

  • Unit cases fail before each fix: the pointer-events second finger, the pinch over two pans, and the shadow-root selection lock.
  • A real-touch proof in Chromium and WebKit: a screen-edge pan on an element wider than its band takes its edge (spec:AST-094 FR18–FR22, DEC-22).
  • Two changesets, the arena's claim comment and a test header now say what the code does.

@vercel

vercel Bot commented Oct 25, 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 29, 2026 10:41pm UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Oct 30, 2026, 5:33 AM UTC

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 25, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 25, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 25, 2026
…d on the restacked head (no emulation; a second finger now gives the swipe up, meta#8336), Android 15 emulator takes (Chrome 124, 540x1200)
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 25, 2026
…der the List reorder

# Conflicts:
#	packages/core/src/utils/pressFeedback.ts
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 25, 2026

@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 can't be approved yet: the new gesture host behaviors rest only on spec:AST-094, a draft this branch adds, and the second-finger rule, holdPageScroll and keepsTouch contradict its FR10 and FR19 as written. An engineering owner needs to decide that direction, either by amending the record and commenting /approve-spec <full head SHA> on this pull request (the author can do this as an engineering owner) or by naming the behaviors to remove. Whatever that decision, these need changes:

  • Rebase once the dependency pull requests land, or retarget the base, so this diff carries the 13 host files instead of 30,301 changed lines.
  • The adaptive compact test hard-codes width < 744px, but spec:AST-012 FR9 defines compact as width below the theme's md point or height below 500, with no component-owned numbers.
  • when.platform is outside spec:AST-012 FR2's closed condition list, and the press selection lock changes stable components under an [experimental] changeset, which spec:AST-017 FR22 does not allow.
  • The motion docs and changeset describe theme motion roles as driving touch motion, but no component reads them yet.
  • Detaching a keepsTouch press tracker can leave its non-passive touchmove listener behind, and the description needs the writing-rubric results for the new record.

[Automated review]


/** Both: presentations such as a sheet in place of a popover. */
export const COMPACT_TOUCH_QUERY =
'(width < 744px) and (pointer: coarse), (height < 500px) and (pointer: coarse)';

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 hard-codes 744px. spec:AST-012 FR9 defines compact as width below the theme's effective md point (768 by default) or height below 500, and architecture:public-component-api INV17 rules out component-owned compact numbers, so coarse-pointer viewports 744–767 px wide get the popover here where FR9 gives the sheet.

if (registration.consumer === consumer) {
registration.consumer = null;
}
this.cleanup(element, registration);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Detaching a keepsTouch: true consumer goes straight to cleanup, which returns early while tap, hover or watcher recognizers stay attached, so the non-passive touchmove listener refresh added for keepsTouch stays too. Calling this.refresh(element, registration) before cleanup removes it.

) {
const ids = recognizer.trackedTouches.map(touch => touch.id);
recognizer.cancel();
this.arena.releaseClaims(ids);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

releaseClaims clears the claim on these touches even when another claiming recognizer, set to recognize simultaneously with this pan, is already active on the same finger; claim() only runs at recognition, so that recognizer never gets the claim back. Releasing only touches no other active claiming recognizer tracks would avoid that.

* is everything else. Pair `ios` with `pointer: 'coarse'` for a touch
* profile, such as touch motion tuned per platform.
*/
platform?: 'ios' | 'other';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

spec:AST-012 FR2 lists width, height, pointer, contrast and motion, and says future environment fields need an explicit addition to that closed vocabulary, so platform needs that amendment first.

Comment thread .changeset/touch-selection-lock.md Outdated
'@astryxdesign/core': patch
---

[experimental] A held finger or pen no longer starts text selection or the iOS callout on a press-tracked control or cell, or on a recognizer created with the new `preventsTextSelection` option (`@astryxdesign/core/gestures/experimental`), as on UIKit controls. The gesture host turns them off for the contact and restores them when it ends, on a non-text input under the finger inside such an element too (WebKit's own style makes every input selectable), and only for recognizers that would take the touch; the document press controller (`usePressFeedback` rows) takes the same lock on any coarse pointer. Text fields keep their selection, a mouse keeps desktop selection, and other pans leave their content selectable.

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 changeset also changes the document press controller behind Button, Item, Link and other stable components; spec:AST-017 FR22 keeps stable runtime behavior out of the [experimental] exception.

Comment thread packages/cli/assets/docs/motion.doc.mjs Outdated
content: [
{
type: 'prose',
text: 'On a touch screen, sheets, alerts, menus, navigation and scrolling play the springs, durations and curves measured from iOS. Each value is a motion role named by its table path, such as `springs.sheetPresent` or `timing.curves.easeInOut`. A theme retunes a role through `motion.springs`, `motion.durations` or `motion.curves`, at its root or in an adaptation rule; a role it leaves alone keeps its measured default.',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No component reads the motion roles or --motion-* variables yet, so this sentence (and “Components read the variable when a motion starts” below) describes behavior builders will not see after retuning a role.

vjeux added 15 commits October 29, 2026 10:09
…achments asks, and only then

The host let the last attachment decide whether an element is an action
group (useGestureRecognizer always passes the option), and never
recomputed it at a detach: a plain attachment after the group's turned
the group off, and a group's attachment released left a recognizer that
never asked taking presses under a fine pointer. Fails until the host
counts the attachments that ask.
…ents asks

The host counts the attachments that pass actionGroup: true and keeps the
element a group while one remains, recomputed at each detach. An
attachment that passes false, as useGestureRecognizer does by default,
no longer turns a group off, and a group's last asking attachment taking
its leave ends the group.
… that content

The presented hit test takes the document's elementFromPoint, which
answers a shadow host for anything inside its open root, and compares
with Node.contains, which stops at the boundary: a recognizer on a
control inside a moving sheet's shadow root gets no finger, and the tap's
click goes to the host. Fails until the hit test descends into open roots
and compares along the flat tree.
Where a moving element is drawn away from its layout box, the host
hit-tests what is drawn under the finger with the document's
elementFromPoint, which answers a shadow host for anything inside its
open root. The hit test now descends through each open root's own
elementFromPoint and compares with the movers along the flat tree, so a
recognizer on a control inside a moving sheet's shadow root gets its
finger and the tap clicks that control.
…nt lets go

The host's touch-action rules sit in an adopted sheet or a style element
per document or shadow root, and were never removed, so a page whose
last recognizer detached kept them, against spec:AST-094 FR24 (nothing
touch-related remains after the last instance unmounts). Fails until a
root's rules go with its last marked element.
…th its last marked element

The touch-action writer records which elements it marked in each
document or shadow root, and when the last one is unmarked (its last
recognizer detached) it removes that root's adopted sheet or style
element, so nothing touch-related remains after the last instance
unmounts (spec:AST-094 FR24). A later mark writes the rules again; an
element marked in another root first lets go of the old one.
… the inline style it reads

- The motion registry, the host's engine gate and the README name the
  presented hit test as an engine workaround (spec:AST-013 FR6) with its
  review condition (re-measure on each iOS release; remove it once iOS
  WebKit hit-tests a compositor-moved element where it is drawn) and its
  regression fixture.
- While a curve runs the animator holds the value it starts from inline,
  so presentation.ts and the README no longer say the inline style holds
  the end.
…core/internal/touch

Core ships the internal entry @astryxdesign/core/internal/touch, which
re-exports the gesture primitives for Astryx's own packages, and the
Lab-import guard fails a Lab import of core outside core's exports
(architecture:react-component-runtime INV13). The README and the barrel's
header named internal workspace imports and said nothing here is
exported; they now name that entry.
…ill needs the element, and the listeners that cancel

The release note, the stream's header, the host's comment and the README
said the stream is one passive listener per event type and that a
document-capture stopPropagation no longer starves the recognizers. Such a
stop never hid a listener on the same node, and some subscriptions cancel.
They now say what changed: an app's window-capture stopPropagation, or a
document-capture stopImmediatePropagation registered before core, no
longer hides a touch; a recognizer that must claim still needs the touch to
reach its element; the gesture host's touchend, click and contextmenu
cancel while a claimer is attached and the page hold's touchmove while it
holds; and the stream stays ahead of an app's window-capture listener only
until a type's listener is re-added. The README's list of blocking
touchmove listeners gains the claimed touch's target and the document
while a claiming element moves.
…default it moves

The {stylexOptions} form of astryxStylex now passes StyleX
treeshakeCompensation: true unless the caller sets it. spec:AST-017 FR3
asks the release note to name the old and new default and the option
that restores the old one; it now does.
…er and for the two stops the input stream fixes

- A still finger with sub-pixel jitter over a scroll view keeps its tap
  and scrolls nothing (spec:AST-094 FR18–FR22).
- A tap is still recognized under an app's window-capture
  stopPropagation, and under a document-capture
  stopImmediatePropagation registered before core's: the recognizers hear
  touches on the window's capture phase.
Chromium and WebKit pass.
…s once

Where nothing that claims is attached, the host's touchend listener is
passive and cannot cancel the engine's own click after a retargeted tap
clicks what is drawn. The shared click guard swallows that late click
whatever is attached; this case pins it, as asked on meta#8293.
meta#8360 now carries the review fixes of the foundation it holds. The two
conflicts are this pull request's own files:
- GestureHost.ts: meta#8360 counts the attachments that ask for an action
  group; here the fine-pointer group listener and the per-event recognizer
  set are gone (every pointer is served, FR43), so the merge keeps the
  count and drops those two.
- GestureHost.test.ts: both sides added the same assertion to the
  second-finger case; the merge keeps this side's comment. meta#8360's
  action-group lifetime case counts a group's own pointerdown under a fine
  pointer, which this pull request replaces with one passive pointerdown
  on any element that uses a gesture (its own idle-listener case), so the
  merge leaves it out.
… attached, in this host's terms

meta#8360's action-group lifetime case pins that an element stays a group
while any attachment asks and stops with the last. Here every element
that uses a gesture is served as a group under a fine pointer, so the
same invariant reads as the element's one passive pointerdown: with two
gestures attached, detaching either keeps it, and detaching the last
removes it. It passes on this head.
meta#8360 carries this pull request's predecessors and the review fixes of
the foundation it holds; this pull request's own diff is now its six
commits (a second finger fails a one-finger pan wherever fingers come
from, and the check reruns once that finger is delivered; a press's
selection lock gets what it landed on; a pinch's second finger on another
pan claims neither; the wider-band edge pan's real-touch proof; text).
Two conflicts:
- GestureHost.ts: the selection lock's target takes meta#8360's presented
  target, which is what the press landed on unless an element under it
  is moving, so it keeps this pull request's fix and meta#8293's correction.
- .changeset/gesture-press-tracking.md: meta#8360's text, which names both
  writers of the press attribute.

@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 needs changes before it can be approved. The gesture host still attaches only where the primary pointer is coarse, while architecture:react-component-runtime INV13 and spec:AST-094 FR19 and FR43 on main now say it attaches for every pointer, so please conform it here (as #8665 does) or keep it out until it does, and update the description, which says the press tracker already follows every pointer. The diff is also 27,428 authored lines, all but 214 of them the content of #8360; landing #8360 and #8589 on their own and rebasing would leave this pull request its own second-finger change.

  • ScreenEdgePanGestureRecognizer accepts a mouse, trackpad or pen, which FR43 keeps off, and PressTracker is a class where INV13 asks for a create… factory.

[Automated review]

Comment on lines +911 to +930
private isActive(recognizer: GestureRecognizer): boolean {
return this.isCoarse || this.perEventRecognizers.has(recognizer);
}

/**
* Whether a press consumer takes input now (FR19; its per-event opt-in,
* an FR19 exception for press feedback pending in AST-094's amendment).
*/
private isConsumerActive(consumer: TouchConsumer): boolean {
return this.isCoarse || this.perEventConsumers.has(consumer);
}

/** Whether anything attached takes input now. */
private needsInput(): boolean {
return (
this.isCoarse ||
this.perEventRecognizers.size > 0 ||
this.perEventConsumers.size > 0
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Under a fine pointer nothing here takes input except perEventPointer participants, so a pan, swipe or long press never runs for a mouse, trackpad or pen, and hover recognizers (line 1459) never hear a desktop mouse. CURRENT architecture:react-component-runtime INV13 says "The gesture host attaches for every pointer, with no touch-only query", and spec:AST-094 FR19 and FR43 say the same. Conforming here, as #8665 does, also means updating the header (lines 12–28), the development warning (lines 1357–1363) and the coarse-only tests.

Comment on lines +72 to +76
constructor(options: ScreenEdgePanGestureRecognizerOptions = {}) {
super({
maximumNumberOfTouches: 1,
hysteresis: UIKIT_SCREEN_EDGE_PAN.hysteresis.value,
...options,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

There is no allowedPointerTypes default here, so wherever the host delivers a mouse or a pen (an iPad's Pencil today, and every pointer once the host follows FR43), a press-drag from the band begins the edge pan. spec:AST-094 FR43 keeps "the screen-edge pan under a mouse, a trackpad, or a pen" off; defaulting allowedPointerTypes to ['touch'], with a mouse and a pen case in the tests, would cover it.

return tap.numberOfTapsRequired === 1 && tap.numberOfTouchesRequired === 1;
}

export class PressTracker implements TouchConsumer {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

architecture:react-component-runtime INV13 keeps classes to the recognizer family ("its base, the arena, and the host") and builds every other module from create… factories. A createPressTracker factory (constructed in one place, usePressTracker.ts) would fit, or INV13 could list this as a known gap.

// compiled (the TypeScript transform drops it as unused), the module is
// never loaded, and its constants never reach the CSS: a media-query key
// fails the build and a value ships as an undefined custom property.
treeshakeCompensation: true,

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 flips the published {stylexOptions} form's default, which no current record covers (spec:AST-080 leaves the bundler integration out of scope). It is unrelated to the gesture host and would be easier to review and release in its own pull request.

vjeux added 9 commits October 29, 2026 12:16
…esture host's subscriptions

The gesture host subscribes no click: the one cancelling click subscriber
is the click guard's, added at a window's first arm and kept. The release
note, the stream's header and the gestures README listed click with the
host's touchend and contextmenu; they now name the guard's own.
meta#8360's input-stream notes no longer list click among the gesture host's
subscriptions. The merge is clean.
… lift and the browser's menu, keeps a kept press's finger, and goes when the page hides

From the review of this pull request, three cases fail on its head:
- an armed press installed the page listeners without the claiming
  ones, so a claimed finger's touchend stayed passive and the browser's
  menu opened during a claimed long press (spec:AST-094 FR21);
- a kept press got its blocking touchmove during an armed press, but its
  moves were cancelled only where the primary pointer is coarse, so a
  held stepper on a touchscreen laptop lost its finger (FR11, DEC-21);
- a page hidden mid-press cancelled the press but kept the page's
  listeners until the next lift anywhere (FR24).
…lift and the browser's menu, keeps a kept press's finger, and goes when the page hides

- A finger's or a pen's armed press now brings the claiming listeners
  (the cancelable touchend and the contextmenu canceller) with the page
  listeners, as wherever the host installs, so a claimed lift clicks
  nothing and a claimed hold opens no browser menu (spec:AST-094 FR21). A
  mouse's press needs neither and adds neither.
- A kept press keeps its finger under any pointer: its target blocks and
  its moves are cancelled once its press is delivered, not only where the
  primary pointer is coarse (FR11, DEC-21).
- A page hidden mid-press releases the armed press as a blur does, so the
  page's listeners go with the cancelled press (FR24).
…'s selection

An action group's press is a long press with no minimum duration, so it
claims at the press's pointerdown, before any movement. The drag
selection hold then cleared the page's selection, so a plain click on a
group's button left its Copy or Cut with nothing to act on. The case
fails on this head: the selection is gone after the pointerdown.
…age's selection

The drag selection hold cleared the page's selection when any mouse or
pen contact was claimed, but an action group's press claims at its
pointerdown, before it has moved or selected anything, so a plain click
on a group's button left its Copy or Cut with nothing to act on. A claim
before any movement now keeps the page's selection: the hold still
refuses a new one, and puts the page's back over a selection that
appears while it runs. A claim after movement clears what its drag
selected, as before (spec:AST-094 FR41).

The case before the new one now waits for its hold to end a task after
the lift, so no hold outlives that test.
…t every pointer does

- GestureHost's header, the gestures README and coarsePointer.ts no
  longer describe the coarse-only host: a finger or a pen takes the
  touch-down lock under any primary pointer, a kept press's finger is
  kept during a fine pointer's press too, and recognizers attach for
  every pointer while the page listeners last a press (spec:AST-094 FR19,
  FR24, FR41, FR43).
- The fine-pointer selection case asserted the replaced rule and passed
  only because it read iOS WebKit's inline lock without iOS WebKit: it
  now asserts the lock a fine pointer's finger and pen take, and that a
  mouse takes none.
- FR41's sentence and its verification row say that a press claimed at
  its own pointerdown, before it moves, keeps the page's selection, while
  a drag that moved before its claim loses what it selected.
…ion, in the present tense

The sentence said a drag that moved before its claim loses the selection
it started, but the hold clears the page's selection then, whatever made
it; and an unclaimed mouse drag kept "today's" behavior, a phrase that
ages. It now says a claim after movement clears the page's selection, a
press claimed at its own pointerdown keeps it, and an unclaimed mouse
drag keeps its released behavior.
This pull request now sits on meta#8665, so a stack carrying it and meta#8665's
other dependants (meta#8676) needs no second GestureHost resolution. Two
hunks in GestureHost.ts's pointerdown, both this pull request's:
- the second-finger check where fingers come from pointer events stays,
  followed by meta#8665's rule that a right click, a pen's barrel button or
  a macOS ctrl-click starts no press;
- the check that runs again once the new finger is delivered stays,
  followed by meta#8665's selection lock call, which no longer takes the
  window.

@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 can't be approved yet: the head now rewrites spec:AST-094 FR41 so that a mouse or pen drag a gesture claims takes no text selection and clears the page's, which current FR41 (a mouse keeps its released behavior) does not allow, so the amendment needs an engineering owner's decision. An engineering owner records it by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner; otherwise say what should change in the amendment. Whatever that decision, these changes are still needed:

  • Land #8360 and #8665 on their own and rebase, since all but 214 of the 28,602 authored lines here are their diff.
  • Map a wheel or trackpad scroll to a pan and a ctrl-wheel to a pinch, as FR43 requires, or stop describing the host as FR43-conformant.
  • Build PressTracker as a create… factory, as architecture:react-component-runtime INV13 requires outside the recognizer family, or record it as a known gap there.
  • Update the description, which still names closed #8315 and does not mention the FR41 amendment.

[Automated review]

acts as a finger's; a mouse makes the context request by a right click, not
a long press (FR43), and otherwise keeps its released behavior
(`spec:AST-017` FR59; DEC-9).
(`spec:AST-017` FR59; DEC-9). A mouse or pen drag that a recognizer claims

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 adds a requirement CURRENT FR41 does not state (a mouse "otherwise keeps its released behavior"), so it needs an engineering owner's decision before the code that implements it can be approved: an engineering owner records it with /approve-spec <full head SHA> on this pull request.

}
};
if (!keepsSelection) {
view?.getSelection()?.removeAllRanges();

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 empties whatever is selected when a moved drag is claimed. On an element that cannot be selected (a grab handle with user-select: none) the browser itself keeps the reader's selection through a mouse drag, so this is where the amendment changes behavior people meet.

* @position Browser adapter of packages/core/src/gestures: turns real events
* into GestureArena input, and carries out what the arena decides
*
* FOR EVERY POINTER

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR43 also says a pan takes wheel and trackpad scrolling and a pinch takes a ctrl-wheel; the host listens for no wheel event, so a pan attached here ignores both. Map them, or keep this header and the changeset to what the host does.

return tap.numberOfTapsRequired === 1 && tap.numberOfTouchesRequired === 1;
}

export class PressTracker implements TouchConsumer {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

architecture:react-component-runtime INV13 keeps classes to the recognizer family (its base, the arena and the host) and builds every other module from create… factories; a createPressTracker factory, or a recorded gap in INV13, would conform.

@vjeux

vjeux commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

In this push: this pull request now sits on #8665, so the host attaches for every pointer here, and the screen-edge pan stays a finger's by #8665's default (283e7b2). The press tracker factory is #8763; the {stylexOptions} default comes from #8360 and stays the owner's decision.

@vjeux

vjeux commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

Folded into #8309 under the maintainers' section plan; the commit credits this PR's authors. Closing; the branch stays.

This branch was successfully deployed

1 active deployment
Preview — 283e7b2e Deployed Oct 29, 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