Skip to content

spec(AST-094): touch presentations feel native by default - #8394

Closed
cixzhang wants to merge 4 commits into
mainfrom
spec/ast-094-touch-native-default-r3
Closed

cixzhang wants to merge 4 commits into
mainfrom
spec/ast-094-touch-native-default-r3

Conversation

@cixzhang

Copy link
Copy Markdown
Contributor

Supersedes #8378 (whose three review rounds were spent), which superseded #8316 and #8052. It carries vjeux's record, credited as co-author, plus every owner ruling since. The record itself contains no pull request references.

What changed from #8378's last head:

  • Keyboard exception: motion that must stay in step with the on-screen keyboard is not a theme role. It rides the keyboard's own motion (spec:AST-099 FR8, architecture:react-component-runtime INV11).
  • Pending owner rulings:
    • DEC-5: FR4 cites the generated motion role table.
    • DEC-6: CSS keyed on the literal touch media query counts as "after hydration" (FR13).
    • DEC-7: a watcher recognizer is passive only (FR20).
  • Already in the record from spec(AST-094): touch presentations feel native by default #8378's rounds:
    • Seven current records point to AST-094.
    • FR11 activation stays the browser's click; the bar-control alternative may come as a later amendment.
    • FR19's scroll-lock and press-owning exceptions, and FR20 watchers.
    • Selector's listbox is in FR26–FR30.

Exact decision needed

Approve spec:AST-094: touch presentations get one native-feeling behavior by default on every touch device, iOS and Android alike. Open questions: OQ5 (the menu's drift allowance), OQ6–OQ8 (opening a sub-menu without a lift, the opening haptic, a withdrawn tentative open), OQ9 (where a menu sits on a compact touch screen) and OQ10 (a sub-menu with its parent visible). Module-level experimental subpaths are closed: motion and gestures stay internal (FR4). Platform look and feel is a non-goal tracked separately. Release velocity is governed by spec:AST-100.

Existing authority searched

  • Current claims this record names as amended for touch presentations:
    • component:Selector DEC-1 (the adaptive query);
    • spec:AST-013 FR3 (an Android Chrome support row);
    • spec:AST-025 FR14 (nested scrolling);
    • spec:AST-057 (Item's swipe constants and FR2);
    • design:user-states DR1/DR3;
    • the press treatment of family:buttons;
    • module:DropdownMenu/useMenuPress FR6.
  • Current claims it keeps and cites:
    • module:DropdownMenu/useMenuPress FR4;
    • design:user-states DR4;
    • spec:AST-043 FR1;
    • spec:AST-012 FR9 (compact);
    • design:reduced-motion;
    • architecture:public-component-api INV14, INV16;
    • spec:AST-017 FR3, DEC-23;
    • spec:AST-002 FR3;
    • architecture:react-component-runtime INV5/INV7;
    • family:overlay-dismissal AV6.
  • Why none of them settles it: no current record states native touch behavior as the default.

Decision

  • One behavior on every touch device: measured values with sources, the same on every platform unless a measured, sourced difference exists. Touch motion is themeable, with the measured values as theme defaults; gesture thresholds stay internal.
  • Motion and gestures: compositor motion a finger can catch. Recognizer arbitration and readings follow the native model. Two press profiles. Exits as native.
  • Reduce Motion: governed by design:reduced-motion DR2 and DR4.
  • When it applies: one rule for when the touch presentation applies, a coarse pointer plus the spec:AST-012 FR9 compact definition where a presentation depends on size. The touch presentation applies after hydration.
  • Defaults and cost: a moved default is restored by the caller's presentation choice. Touch work costs nothing under a fine pointer.
  • Menus and popovers under a finger (FR26–FR35):
    • The lift decides, and the highlight follows the finger with one lit row.
    • A lift outside keeps a menu open.
    • A menu opens on press: at once in a fixed bar, or after 150 ms with no scroll inside a scroll view. The opening finger's handoff applies.
    • Edge autoscroll while the finger is held.
    • Menus and Popover grow from the trigger and shrink back.
    • A pan outside dismisses, and pinch stays available.
    • ContextMenu's long press and lift.
    • A sub-menu drills in as DropdownMenu's does.
    • A presentation takes no input while it grows.
    • useMenuPress hands its finger rules here. DropdownMenu, ContextMenu and Popover point here.
  • Release decisions (FR36–FR40):
    • One decision at the release, from projected travel against a commit point.
    • Moving back cancels, and the settle continues the finger.
    • A keyboard and mouse path stays available.
    • Velocity comes from spec:AST-100.

Rejected alternatives

  • Per-platform behavior tables (one native-feeling behavior on every touch device is the ruling).
  • A generic restoring prop per moved default (presentation is the way back, INV16 and DEC-23).

Claim scope and non-goals

  • Out of scope: pointer presentations, scroll physics, which components adopt a touch presentation, and platform-matched look and feel (OQ3).
  • Open: module-level experimental subpaths (OQ4).

Evidence and implementation relationship

The values come from UIKit read on the simulator, Apple documentation, WWDC sessions and WebKit's source. Implementation stacks on this record. Implementations: #8078 (menu press and handoff), #8080 (menu grow and collapse), #8187 and #8198 (Popover grow and pan-outside dismissal), #8201 (ContextMenu lift), #7308 (ContextMenu under a finger), #8341 (the release decision), #8220 (sub-menus in place), #8223 (the presentation hold), #8195 (the menu cell profile); #8089 (menu placement on a phone) is OQ9.

Writing rubric results

  • R1 narration: none. Amendments are present-tense rules, and the record carries its deciders.
  • R2 research in the record: none. Measurements are cited, not reproduced.
  • R3 evidence naming a change: none.
  • R4 rejected alternatives over one line or outside a decision: none.
  • R5 pull request or issue references remaining: none in the records.
  • R6 ruled open questions still listing options: none. OQ1, OQ2 and OQ5–OQ10 are unanswered; DEC-5–DEC-7 await an owner ruling.

Scope

  • This PR contains specification records only.
  • It records observable behavior and preserves equivalent internal implementations (FR1, FR9, FR13 and FR24 are stated as observable contracts, architecture:knowledge-contracts INV18).
  • Any named internal mechanism is intentionally public, names its dependent caller/system, and explains why an equivalent implementation would not satisfy the contract.
  • Verification states the evidence layer and failure signal without prescribing CI job/workflow topology.
  • It records one intentional durable decision, not a rescue for a separable tagalong.
  • The canonical knowledge owner, affected current claims, and overlapping open work are named; any ownership collision is resolved or called out for human decision.
  • Adjacent API, visual, accessibility, composition, and implementation facts remain outside scope unless this exact decision depends on them.
  • Public text and artifacts contain no internal Meta context.

Validation

  • pnpm check:knowledge: aligned.
  • Prettier: clean.
  • git diff --check: clean.

Touch presentations get one native-feeling behavior by default on every
touch device: measured values, compositor motion a finger can catch,
recognizer-tracked gestures, two press profiles, Reduce Motion per
design:reduced-motion, menus and popovers under a finger (FR26-FR35), and
one release decision for every drag that commits (FR36-FR40). Touch motion
is themeable through use-named roles, except motion that must stay in step
with the on-screen keyboard (AST-099 FR8). The seven current records it
amends point to it.

Retries #8378, whose review rounds were spent, carrying its last revision
plus the keyboard exception and three decisions pending an owner ruling
(DEC-5 the generated role table, DEC-6 touch media-query CSS, DEC-7 passive
watchers).

Co-authored-by: vjeux <197597+vjeux@users.noreply.github.com>
@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 25, 2026 12:46pm 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 25, 2026, 1:17 PM UTC

@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Oct 25, 2026
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

Current run: The current change has no visual or preview-producing scope. Visual checks are not applicable; preview links are not shown.

The exact-head preview is not available yet.


Generated by PR Enrichment workflow | View current CI run

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This spec is not ready to approve yet: no engineering owner has approved spec:AST-094 or its amendments to eight current records at this head, and DEC-5 to DEC-7 still read "pending owner ruling". Once those three rulings are settled in the record, an engineering owner (the author included, as one) records the decision by commenting /approve-spec <full head SHA> on this pull request. Whatever that decision, these need fixing first:

  • FR29 moves DropdownMenu's released presentation default ('popover') and useMenuPress's released 500 ms longPressDelayMs, so please name both in FR25 and the Current-state impact and mark the trigger half released in useMenuPress.spec.md.
  • DEC-5 to DEC-7 are pending inside a record marked current and accepted, so please name their decider, or mark them and the sentences they settle (FR4, FR13, FR20) as proposed.
  • FR4 cites a generated motion role table that astryx docs motion does not contain, so the 17 named roles have no recorded default or source.
  • FR33 gives no presentation way back for the ContextMenu lift, unlike FR29 for DropdownMenu.
  • The DR1 amendment in docs/design/user-states.md replaces the pressed-overlay paint with FR11, which only sets timing, so please keep the paint and move only the timing, as the DR3 amendment does.

[Automated review]

Comment on lines +294 to +298
on FR26–FR28 apply. `presentation="popover"` keeps today's open on a tap;
the default is unset (`architecture:public-component-api` INV16). The delay and distances are internal values and gain no new props
(`spec:AST-002` FR3); A `module:DropdownMenu/useMenuPress` caller that sets the released
`longPressDelayMs` gets that wait in a fixed bar and in a scroll view alike,
which keeps the released behavior (`spec:AST-017` FR3).

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 moves two released defaults: DropdownMenu's documented presentation default ('popover') becomes unset, and a useMenuPress caller that leaves longPressDelayMs unset loses the released 500 ms wait. FR25 and the Current-state impact name only Selector's moved default, so please add both.

Comment on lines +99 to +100
(`architecture:theme-tokens` INV3); the generated motion role table
(`astryx docs motion`) lists every role with its kind and default. The role's default value is

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

astryx docs motion (packages/cli/assets/docs/motion.doc.mjs) has no role table at this head, so the 17 roles named in FR4, FR31 and FR34 have no recorded default or source, which FR2 requires next to each value.

Comment on lines +319 to +326
- **FR33 — A ContextMenu under a finger.** With a finger or pen, the long
press that opens a ContextMenu MUST NOT close it at the lift, and a press
outside it follows FR32. On every touch device, a ContextMenu that a held
finger opens on a block trigger MUST lift the trigger above the page and
show the menu beside it, with no row lit. A tap outside closes the menu and
reaches nothing beneath it, and closing returns the trigger to its place.
Under reduced motion FR8 applies. An inline trigger keeps today's menu, and
a menu presented as a bottom sheet follows the sheet.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR29 gives DropdownMenu a presentation way back, but FR33 gives none for the ContextMenu lift, and ContextMenu's released default is presentation = 'popover'. Please state which INV16 branch the lift falls under.

Comment on lines +518 to +542
### DEC-5 — FR4 cites the generated motion role table

**Reference:** `spec:AST-094/DEC-5`
**Decider:** pending owner ruling

FR4 names its roles by use and cites the generated motion role table instead
of copying it, so a new component table cannot drift from the record.

### DEC-6 — CSS keyed on the touch media query counts as after hydration

**Reference:** `spec:AST-094/DEC-6`
**Decider:** pending owner ruling

FR13's "only after hydration" governs a presentation decided in script. A
style keyed on the literal touch media query conforms: the server and
hydrating markup are identical, and the browser applies the style at first
paint.

### DEC-7 — A watcher recognizer is passive only

**Reference:** `spec:AST-094/DEC-7`
**Decider:** pending owner ruling

A recognizer that never claims registers only passive listeners (FR20), so
watching a touch never delays the browser's scroll.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

These three decisions are pending inside a record marked authority: current and phase: accepted, and the sentences they settle (FR4, FR13, FR20) carry no "proposed" marker. Please name the decider, or mark them proposed as useMenuPress.spec.md does for its pending FR8 and DEC-4.

Comment thread docs/design/user-states.md Outdated
Comment on lines +55 to +56
or drag ends. Under a finger, a touch presentation's press feedback follows
`spec:AST-094` FR11's press profiles instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

"Instead" removes the requirement to paint --color-overlay-pressed under a finger, but FR11 only sets when the highlight starts, drops and activates. Suggest: "Under a finger, the overlay's timing follows spec:AST-094 FR11's press profiles", which matches the DR3 amendment below.

| highlight | DOM focus, or a caller callback | one lit row; focus with `preventScroll` in a menu, `aria-activedescendant` in a picker | focus | `module:DropdownMenu/useMenuPress` | stable |
| stray-click window | 400 ms, or the next `pointerdown` | how long after a tracked release the browser's click is still swallowed | `MENU_PRESS_STRAY_CLICK_MS` | `module:DropdownMenu/useMenuPress` | stable |
| settle time | 300 ms | proposed: how long an opening press must last before its release may act | `MENU_PRESS_SETTLE_MS` | `module:DropdownMenu/useMenuPress` | proposed |
| long-press delay | as `spec:AST-094` FR29 states (none in a fixed bar; 150 ms in a scroll view) | proposed: how long a held finger waits on a trigger before the menu opens (`spec:AST-094` FR29). A caller that sets `longPressDelayMs` gets that wait in a fixed bar and in a scroll view alike, which keeps the released behavior. | `longPressDelayMs` | `module:DropdownMenu/useMenuPress` | proposed |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

longPressDelayMs shipped in 0.6.6 with a 500 ms default, and AST-094 FR29 calls it released, but this row and the Public contract row still list the trigger half as proposed.

…roposals

- FR25 and Current-state impact name the four released defaults FR29 and
  FR33 move (Selector's adaptive policy, DropdownMenu's and ContextMenu's
  omitted presentation, useMenuPress's 500 ms longPressDelayMs) and each way
  back; useMenuPress's trigger half is released; ContextMenu's compatibility
  note says so.
- FR33: presentation="popover" keeps the released ContextMenu without the
  lift.
- FR4 lists its 17 roles with defaults and sources. DEC-5 to DEC-7 and the
  FR4, FR13 and FR20 sentences they settle are marked proposed.
- design:user-states DR1 keeps the pressed overlay; only its timing follows
  FR11 under a finger.

Co-authored-by: vjeux <197597+vjeux@users.noreply.github.com>
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 25, 2026
@vjeux

vjeux commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Three points for the owner's ruling. None of them is in this pull request's diff yet.

1. architecture:interaction-modality INV10, Lab's velocity. INV10 ends: "Lab cannot import the tracker; a Lab gesture keeps one local tracker with the same blend and stillness interval, so it reports the same velocity for the same motion."

  • Lab's gestures don't track velocity themselves. They attach Core's recognizers (PanGestureRecognizer, ScreenEdgePanGestureRecognizer) from Core's internal gestures module and read velocity() from them, which reads Core's one tracker.
  • As written, every Lab gesture would need its own copy of the filter. That copy can drift, which is what INV10 exists to prevent.
  • Proposed replacement for that sentence: "Lab reads gesture velocity only through Core's recognizers (velocity() on a pan, or on a scroll view's pan for a scrolling surface), from Core's internal gestures module. It never imports the tracker and never keeps its own sample buffer, velocity math or release filter, so it reports Core's velocity for the same motion."
  • The verification row's failure "a Lab tracker reporting a different velocity for the same stream" would become "a Lab component with its own sample buffer, velocity math or release filter".
  • INV10 isn't in this diff. It could ride this revision, which already amends other current records, or a change of its own.

2. FR20 and watchers, the part of the earlier amendment that's still open. DEC-7 settles that a watcher registers only passive listeners. FR20 still says that when the browser takes a touch, "active ones are cancelled", which includes an active watcher.

  • The watcher in the gesture host follows the scroll to the lift instead, so a tab bar that minimizes while the person scrolls keeps hearing the scroll.
  • Proposed addition to FR20: "A watcher is not cancelled when the browser takes the touch: it follows the scroll to the lift."
  • If the watcher should stop instead, the host will follow that.

3. The press selection lock, which no record states yet. On a phone, a finger resting on a press-tracked control or cell (a slider, a segmented control, a stepper, a row's checkbox) starts a text selection or opens the loupe. UIKit's controls and cells never do: their labels aren't selectable text; only text views and fields are.

  • Measured on iOS 26.2 Safari with a 1.5 s still hold: without the lock, the row, the checkbox and the slider each start a selection with the loupe at about 650 ms. With it, none do.
  • Proposed requirement, beside FR19: "While a finger is down on a press-tracked control or cell, text selection and the callout are off on that element, so a hold or a drag never starts a selection or the loupe. A pen does the same where the primary pointer is coarse. A mouse, a trackpad and a pen on a desktop tablet never take the lock, so desktop selection is unchanged (spec:AST-017 FR59). A drag that doesn't ask for it, such as a sheet's or a pager's, leaves its content selectable. A text field keeps its selection, and a link keeps its native callout and preview."

@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 spec is not ready to approve yet: no engineering owner has approved spec:AST-094 or its amendments to eight current records at this head, and DEC-5 to DEC-7 are still proposed. Please fix the two points below in a new commit; then an engineering owner (the author included, as one) records the decision and the DEC-5 to DEC-7 rulings by commenting /approve-spec <full head SHA> on this pull request.

  • DropdownMenu.spec.md and ContextMenu.spec.md still say the released default is preserved and name no presentation migration, while FR25 moves both presentation defaults with presentation="popover" as the way back; please name that change and its migration in both records.
  • FR29's open-on-press rule is scoped to every press-model surface, so ContextMenu (whose FR5 now cites FR26–FR30), sub-menu rows and Selector would open on press too; please limit FR29 to the DropdownMenu trigger and have ContextMenu FR5 cite FR26–FR28 and FR30.

[Automated review]

## Compatibility and migration

- Released default: `popover`
- Released default: `popover`. Under a finger, `spec:AST-094` FR33's lift

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 line now moves ContextMenu's default under a finger, but the next lines still say defaults are preserved with "Migration decision: none" (lines 49-52), and DropdownMenu.spec.md line 53 still says "Released default preserved: yes" although FR25 moves its default too. Please name the change and presentation="popover" as the migration in both records (spec:AST-017 FR3).


### Menus and popovers under a finger

FR26–FR30 apply to every surface that carries the press model of

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 scope makes FR29's open-on-press rule apply to ContextMenu, sub-menu rows and Selector's trigger too. ContextMenu FR5 now cites FR26–FR30 while a ContextMenu opens by long press (FR33), and OQ6 says a sub-menu drills in at the lift. Suggest limiting FR29 to the DropdownMenu trigger and citing FR26–FR28 and FR30 from ContextMenu FR5.

@vjeux

vjeux commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

FR4's two sub-menu springs differ from the ones UIMenu itself uses, and UIKit's own values fit the captured frames better.

iOS 26.2 simulator, iPhone 17 Pro, a pull-down menu (Alpha, Beta, Sort By ▸, Delete), every view read per 60 Hz tick, with each UIViewSpringAnimationBehavior UIKit starts logged (2026-10-24). UIKit starts the first a few milliseconds after the lift on every sub-menu row (four captures) and the second on every header back (three):

Role UIKit's spring Fit to the box frames (rms, best start) FR4 today Its rms
springs.subMenuOpen damping ratio 0.85, response 0.4 s 0.12 pt over the 99 pt growth (11 frames) 0.84, 0.415 s 0.48 pt
springs.subMenuBack damping ratio 1, response 0.4 s 0.28 pt over the 99 pt shrink (12 frames) 1, 0.385 s 0.79 pt

The other springs UIKit starts at those moments ((1, 0.5), (1, 0.3), (1, 0.2)) miss the box by 2 to 8 pt. A free single-spring fit of the same frames lands on the same springs: (0.86, 0.395) and (0.98, 0.41). The frames are listed in the sources of motion/uikit/springs.ts in #8220.

Proposal: FR4 lists springs.subMenuOpen as damping ratio 0.85, response 0.4 s, and springs.subMenuBack as damping ratio 1, response 0.4 s, sourced as UIKit's own spring for UIMenu's sub-menu opening and header back (iOS 26.2 simulator, 2026-10-24). #8220 will ship the same values.

…gration

- FR29's open-on-press rule covers DropdownMenu's trigger only; ContextMenu,
  sub-menu rows and Selector keep their own opening, and ContextMenu FR5
  cites FR26-FR28 and FR30.
- DropdownMenu and ContextMenu name the changed default under a finger and
  its migration, presentation="popover" (AST-017 FR3).

Co-authored-by: vjeux <197597+vjeux@users.noreply.github.com>

@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 spec is not ready to approve yet: no engineering owner has approved spec:AST-094 or its amendments to eight current records at this head, DEC-5 to DEC-7 are still proposed, and the requests in this pull request's comments for UIKit's own sub-menu springs (FR4) and for FR20 to stop cancelling watchers are not settled in the record. Please fix the point below in a new commit; then an engineering owner (the author included, as one) records the decision and those rulings by commenting /approve-spec <full head SHA> on this pull request.

  • useMenuPress.spec.md's Compatibility and migration section still names DEC-3 as the only moved default, and DropdownMenu.spec.md still calls the change "additive documentation"; please name the longPressDelayMs move there, with passing longPressDelayMs as its migration, and restate DropdownMenu's compatibility class the way ContextMenu.spec.md does.

[Automated review]

| highlight | DOM focus, or a caller callback | one lit row; focus with `preventScroll` in a menu, `aria-activedescendant` in a picker | focus | `module:DropdownMenu/useMenuPress` | stable |
| stray-click window | 400 ms, or the next `pointerdown` | how long after a tracked release the browser's click is still swallowed | `MENU_PRESS_STRAY_CLICK_MS` | `module:DropdownMenu/useMenuPress` | stable |
| settle time | 300 ms | proposed: how long an opening press must last before its release may act | `MENU_PRESS_SETTLE_MS` | `module:DropdownMenu/useMenuPress` | proposed |
| long-press delay | released 500 ms when set; unset, as `spec:AST-094` FR29 states (none in a fixed bar; 150 ms in a scroll view) | how long a held finger waits on a trigger before the menu opens. A caller that sets `longPressDelayMs` gets that wait in a fixed bar and in a scroll view alike, which keeps the released behavior (`spec:AST-094` FR25). | `longPressDelayMs` | `module:DropdownMenu/useMenuPress` | stable |

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 row moves the hook's released 500 ms default, as spec:AST-094 FR25 says, but the Compatibility and migration section (lines 84-90) still names DEC-3 as the only moved default and gives no migration for this one. Please name the longPressDelayMs move there, with passing longPressDelayMs as its migration (spec:AST-017 FR3).

`presentation`, released as `'popover'`, follows `spec:AST-094` FR29 (open
on press) under a finger; `presentation="popover"` keeps the released
behavior (`spec:AST-094` FR25). Mouse and keyboard are unchanged.
- Compatibility class: additive documentation; the press-model behavior

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Line 53 now says the released default is not preserved under a finger, but this line still calls the change additive documentation and places the behavior delta in useMenuPress, while spec:AST-094 FR29 and FR25 own it. Suggest the wording ContextMenu.spec.md uses: the default under a finger changes, with presentation="popover" as the migration.

…nu springs; handoff after a ContextMenu hold

- useMenuPress names the longPressDelayMs move and its migration (pass
  longPressDelayMs: 500); DropdownMenu restates its compatibility class.
- FR4: the sub-menu springs take UIKit's own UIMenu values (0.85/0.4 s and
  1/0.4 s), measured on the iOS 26.2 simulator, a correction under FR2.
- Proposed DEC-7: a watcher is not cancelled when the browser takes the
  touch; it follows the scroll to the lift.
- FR33: after a held finger opens a ContextMenu, the opening finger's
  handoff applies before FR26-FR28.
- FR17: a Lab gesture reports Core's release velocity for the same motion
  (AST-100 FR1, interaction-modality INV10).

Co-authored-by: vjeux <197597+vjeux@users.noreply.github.com>
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 25, 2026
Its record is under review in its own pull request (meta#8394); this stack no
longer carries an older draft of it. Nothing here cites it.

@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 spec is not ready to approve yet: no engineering owner has approved spec:AST-094 or its amendments to eight current records at this head, and DEC-5 to DEC-7 are still proposed. Please fix the two points below in a new commit; then an engineering owner (the author included, as one) records the decision, the DEC-5 to DEC-7 rulings and whether architecture:interaction-modality INV10 stands by commenting /approve-spec <full head SHA> on this pull request.

  • FR17's new clause that a Lab gesture's access path "follows spec:AST-017 FR21 once that is settled" gives Lab's velocity a second owner beside INV10, which spec:AST-100 FR1 names; please drop it, or amend INV10 here if the owner adopts vjeux's rewrite.
  • FR19 still says every recognizer that begins must claim its touches through a non-passive listener, which the watcher in proposed DEC-7 and FR20 never does; please exempt watchers there if DEC-7 stands.

[Automated review]

Comment on lines +233 to +236
and its translation excludes that travel. Release velocity is governed by `spec:AST-100`: a Lab gesture
reports the same release velocity as Core's tracker for the same motion
(`spec:AST-100` FR1, `architecture:interaction-modality` INV10), and its
access path follows `spec:AST-017` FR21 once that is settled.

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 clause gives Lab's velocity path a second owner: spec:AST-100 FR1 already says architecture:interaction-modality INV10 "owns the source in Core and how a Lab component matches it", and INV10 says "Lab cannot import the tracker; a Lab gesture keeps one local tracker". FR21 is current too, and FR4 says the gesture machinery publishes no /experimental subpath. Suggest ending the sentence at "for the same motion (spec:AST-100 FR1, architecture:interaction-modality INV10).", or amending INV10 in this pull request if vjeux's rewrite is adopted.

Comment on lines +245 to +247
touch listener is registered (FR24). A recognizer that begins MUST claim its
touches by cancelling `touchmove` through a non-passive listener on its
element. A `touchmove` of a touch no recognizer owns MUST NOT be cancelled, with

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A watcher that follows the scroll has begun but never claims (proposed DEC-7 and FR20), so this sentence obliges it to cancel touchmove through a blocking listener, which DEC-7 forbids. If DEC-7 stands, suggest: "A recognizer that begins, other than a watcher (DEC-7), MUST claim its touches …".

@cixzhang cixzhang closed this Oct 25, 2026
@cixzhang
cixzhang deleted the spec/ast-094-touch-native-default-r3 branch October 25, 2026 17:37

This branch was successfully deployed

1 active deployment
Preview — 1c99f147 Deployed Oct 25, 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:spec-owner-review Current knowledge records await owner approval

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants