Skip to content

feat(core): on the web, a trackpad or a mouse wheel scrolling past a BottomSheet's content pulls the sheet (spec:AST-094 FR43) - #8704

Draft
vjeux wants to merge 2355 commits into
meta:mainfrom
vjeux:uikit/c17-sheet-wheel
Draft

vjeux wants to merge 2355 commits into
meta:mainfrom
vjeux:uikit/c17-sheet-wheel

Conversation

@vjeux

@vjeux vjeux commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Depends on #8386 and #8676. Review only this PR's change: https://github.com/vjeux/astryx/compare/0a3bb823ed09f93ffeec5f08a501a5376ad97753..9f6bc54496032ffd96a7bb0f6d55fd9a7805c9a9

Primary intent

On the web, a trackpad or a mouse wheel pulls a BottomSheet the way a drag does, proven by tests.

User or maintainer impact

On a desktop, scrolling over a sheet did nothing. Now:

  • Over the handle, scrolling up pulls the sheet down and scrolling down pulls it up.
  • Over the content, a scroll pulls the sheet only once the content is at its edge, as a finger does.
  • The pull ends 100 ms after the last scroll and settles like a drag's release. A wheel's notches carry no release speed, so three quick notches rest on a detent; a trackpad keeps its speed.

Problem and solution fit

spec:AST-094 FR43 has a pan take wheel and trackpad scrolling. #8676 gives every pan both scroll types, and #8386 puts every pointer on the sheet's pans, so with both merged the pull works with no sheet code of its own. Options:

  1. Opt the sheet's pans in explicitly: redundant.
  2. Rely on the default and pin the sheet's behavior with tests (chosen): this PR's own change is the tests, the changeset and two comments.

Authority

spec:AST-094 FR43, FR36 (the release), FR14 (the content's edge); spec:AST-107 FR7 with INV13's gaps (#8751).

Change and evidence

Desktop Chrome, a trackpad scrolling up at the content's top, then down over the handle (without #8676, then this PR):

Trackpad scroll at the content top, then over the handle

Without #8676 This PR
Ten 12 px scrolls up over the content no movement sheet pulled 110 px, then half detent
Ten scrolls down over the handle no movement back to the tall detent
Three quick 100 px wheel notches no movement half detent, not closed

Scope

  • This PR has one primary intent.
  • Independently removable deltas were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

How to check, in the Snap points story on a laptop: scroll up with two fingers on the trackpad while the content is at its top (the sheet pulls down, then settles); scroll down over the handle (it rises); click a mouse wheel three times quickly (it rests on a detent).

What ran: the new hook tests fail on #8386 without #8676 (4 of 5) and pass here (the notch test caught an earlier #8676 regression, since fixed). The Chromium wheel specs pass; core, lab and the sheet's WebKit tests pass. touch-support-bundle fails here, not on main; #8671 replaces that check.

vjeux added 6 commits October 27, 2026 07:09
…r along the flat tree, and a claimed touch finds its pointer finger wherever fingers come from pointer events) into meta#8293
…r along the flat tree, and a claimed touch finds its pointer finger wherever fingers come from pointer events) into meta#8356
…r along the flat tree, and a claimed touch finds its pointer finger wherever fingers come from pointer events) into meta#8358
…starts; useLongPress on each axis; meta#8336: the host compares a finger with a scroller along the flat tree, and a claimed touch finds its pointer finger wherever fingers come from pointer events) into the every-pointer host
…in, as documented; meta#8336: the host compares a finger with a scroller along the flat tree, and a claimed touch finds its pointer finger wherever fingers come from pointer events) into meta#8360

# Conflicts:
#	packages/core/src/hooks/useLongPress.ts
…he press; meta#8358: useLongPress on each axis; meta#8336: the host compares a finger with a scroller along the flat tree, and a claimed touch finds its pointer finger wherever fingers come from pointer events) into the wheel input

# Conflicts:
#	packages/core/src/gestures/GestureHost.ts
@vercel

vercel Bot commented Oct 27, 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 30, 2026 3:15am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Oct 30, 2026, 4:43 PM UTC

@github-actions github-actions Bot added needs:design-review Affects visuals — Design should review needs:spec-owner-review Current knowledge records await owner approval labels Oct 27, 2026
vjeux added 5 commits October 27, 2026 07:21
…nger's (spec:AST-094 FR21, FR43)

A pen on an iPad sends its pointer events and then its stylus touches; the
host follows the pen through its pointer events and leaves the stylus
touches alone. So when a recognizer claimed a pen's tap, its stylus
touchend went uncancelled, and Safari synthesized the mousedown that
focuses natively and the click. FR21 cancels the touchend of a touch a
gesture takes, and FR43 makes a pen's gestures as a finger's. Fails until
the host cancels it; a second case keeps an unclaimed pen's lift the
browser's.
…ger's (spec:AST-094 FR21, FR43)

The host remembers whether a gesture took a pen's lift (its pointerup's
dispositions, where the host reads Touch Events) until the pen's stylus
touchend, which an iPad sends after the pointer events, and cancels that
touchend then, so Safari synthesizes no compatibility mousedown, with its
native focus, and no click. A stylus touchend whose pen is still down and
claimed is cancelled too; a new pen press forgets a lift that never got
its touchend, as on a pen that sends no Touch Events.
… the presented start

A zoom stage already drives its photo with an animator (pinch, pan,
settle), and the zoom's grow is a rect morph on the same element: two
animators would overwrite each other's channels. createRectMorph takes
that animator in `animator` and plays on it; dispose leaves it to its
owner. The morph's presentedRect then reads the stage's own transform, so
a dismissal from a zoomed photo starts from the shown rect.

A present or a dismissal also takes the animator's `start`: with
'presented', the element holds its first values until two frames have
presented it, so a surface that appears late (a dialog's first frame in
WebKit) plays the whole curve.

Both new cases fail before this change and pass after.
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR

🧪 Sandbox Preview

View Sandbox for this PR

Modified Components

MultiSelector (@astryxdesign/core) · View in Storybook
Metric Before After Delta
Entry File (ESM) 273B 273B 0B
Lines of Code 2642 2642 -
Complexity Very High Very High (344) -
Popover (@astryxdesign/core) · View in Storybook
Metric Before After Delta
Entry File (ESM) 412B 412B 0B
Lines of Code 977 977 -
Complexity Very High Very High (145) -
MobilePowerSearch (@astryxdesign/lab) · View in Storybook
Metric Before After Delta
Entry File (ESM) 336B 336B 0B
Lines of Code 2505 2505 -
Complexity Very High Very High (319) -

Component Size

Component Import before Import after Delta CSS before CSS after Delta
core/AlertDialog 57.0KB 57.6KB +604B 12.4KB 12.4KB 0B
core/AppShell 58.0KB 58.6KB +547B 11.6KB 11.6KB 0B
core/AvatarGroupOverflow 40.1KB 40.7KB +631B 6.4KB 6.4KB 0B
core/Banner 48.0KB 48.5KB +592B 9.9KB 9.9KB 0B
core/BaseTypeahead 54.5KB 55.0KB +554B 9.9KB 9.9KB 0B
core/BottomSheet 33.9KB 71.0KB +37.1KB ⚠️ 7.9KB 8.0KB +98B
core/BottomSheetSwitcher 14.8KB 14.8KB 0B 3.3KB 3.3KB 0B
core/BreadcrumbItem 66.5KB 67.3KB +784B 11.0KB 11.0KB 0B
core/Button 43.4KB 44.0KB +602B 9.2KB 9.2KB 0B
core/Calendar 55.1KB 55.6KB +598B 10.0KB 10.0KB 0B
core/Carousel 50.4KB 51.0KB +632B 10.2KB 10.2KB 0B
core/ChatComposer 60.8KB 61.4KB +593B 10.8KB 10.8KB 0B
core/ChatComposerInput 55.9KB 56.5KB +570B 10.1KB 10.1KB 0B
core/ChatComposerTokenElement 55.9KB 56.5KB +570B 10.1KB 10.1KB 0B
core/ChatDictationButton 46.6KB 47.2KB +585B 9.5KB 9.5KB 0B
core/ChatLayout 49.0KB 49.6KB +610B 9.9KB 9.9KB 0B
core/ChatLayoutScrollButton 46.5KB 47.1KB +592B 9.6KB 9.6KB 0B
core/ChatSendButton 46.0KB 46.5KB +575B 9.2KB 9.2KB 0B
core/CheckboxInput 50.1KB 50.6KB +560B 9.3KB 9.3KB 0B
core/CheckboxListItem 54.2KB 54.8KB +546B 10.5KB 10.5KB 0B
core/ClickableCard 12.8KB 13.4KB +626B 6.9KB 6.9KB 0B
core/CodeBlock 60.7KB 61.2KB +584B 10.7KB 10.7KB 0B
core/Collapsible 11.7KB 12.3KB +608B 4.2KB 4.2KB 0B
core/CommandPalette 51.0KB 51.7KB +732B 11.8KB 11.8KB 0B
core/CommandPaletteItem 8.4KB 9.0KB +596B 3.5KB 3.5KB 0B
core/ComplexSelector 56.0KB 56.5KB +580B 10.6KB 10.6KB 0B
core/ContextMenu 74.7KB 75.6KB +865B 14.6KB 14.7KB +77B
core/ContextMenuItem 53.0KB 53.6KB +630B 9.6KB 9.6KB 0B
core/DateInput 99.7KB 136.6KB +37.0KB ⚠️ 14.8KB 14.9KB +85B
core/DateRangeInput 69.5KB 70.1KB +587B 11.2KB 11.2KB 0B
core/DateTimeInput 109.8KB 146.6KB +36.8KB ⚠️ 15.2KB 15.3KB +89B
core/DialogHeader 49.0KB 49.5KB +580B 9.8KB 9.8KB 0B
core/DrawerHeader 49.1KB 49.6KB +552B 11.2KB 11.2KB 0B
core/DropdownMenu 72.8KB 73.8KB +987B 14.7KB 14.8KB +78B
core/DropdownMenuCheckboxItem 16.1KB 16.7KB +617B 5.6KB 5.6KB 0B
core/DropdownMenuItem 15.4KB 16.0KB +611B 5.2KB 5.2KB 0B
core/DropdownMenuRadioItem 16.2KB 16.8KB +607B 5.6KB 5.6KB 0B
core/DropdownMenuSubMenu 58.2KB 58.9KB +726B 9.5KB 9.5KB 0B
core/FileInput 54.3KB 54.8KB +546B 10.3KB 10.3KB 0B
core/IconButton 43.5KB 44.1KB +602B 9.2KB 9.2KB 0B
core/Item 11.4KB 11.9KB +606B 4.7KB 4.7KB 0B
core/LayerProvider 63.4KB 64.0KB +600B 10.1KB 10.1KB 0B
core/Lightbox 51.3KB 51.9KB +565B 9.8KB 9.8KB 0B
core/Link 43.7KB 44.2KB +590B 7.6KB 7.6KB 0B
core/ListItem 53.7KB 54.2KB +554B 10.5KB 10.5KB 0B
core/Markdown 144.5KB 145.2KB +759B 17.4KB 17.4KB +85B
core/MobileNav 51.2KB 51.7KB +555B 10.1KB 10.1KB 0B
core/MobileNavToggle 46.4KB 46.9KB +572B 9.4KB 9.4KB 0B
core/MoreMenu 73.2KB 74.1KB +921B 14.7KB 14.8KB +78B
core/MultiSelector 73.1KB 73.6KB +584B 14.6KB 14.7KB +95B
core/NumberInput 55.9KB 56.4KB +598B 10.7KB 10.7KB 0B
core/Outline 28.8KB 29.3KB +589B 4.0KB 4.0KB 0B
core/Pagination 84.9KB 85.7KB +775B 15.3KB 15.4KB +90B
core/Popover 50.0KB 50.6KB +582B 12.1KB 12.2KB +87B
core/PowerSearch 158.2KB 195.0KB +36.8KB ⚠️ 19.9KB 20.0KB +101B
core/RadioListItem 52.4KB 52.9KB +571B 9.7KB 9.7KB 0B
core/SegmentedControlItem 8.6KB 9.2KB +597B 3.9KB 3.9KB 0B
core/SelectableCard 12.8KB 13.4KB +623B 7.1KB 7.1KB 0B
core/Selector 76.5KB 77.2KB +735B 15.0KB 15.1KB +92B
core/SelectorOption 14.5KB 15.1KB +601B 5.1KB 5.1KB 0B
core/SideNav 58.1KB 58.7KB +588B 10.6KB 10.6KB 0B
core/SideNavCollapseButton 46.8KB 47.3KB +573B 9.5KB 9.5KB 0B
core/SideNavHeading 54.9KB 55.4KB +564B 10.1KB 10.1KB 0B
core/SideNavItem 54.6KB 55.2KB +551B 10.1KB 10.1KB 0B
core/Step 32.6KB 33.1KB +582B 5.3KB 5.3KB 0B
core/Stepper 47.5KB 48.1KB +567B 9.6KB 9.6KB 0B
core/Switch 48.5KB 49.1KB +579B 9.3KB 9.3KB 0B
core/Tab 9.7KB 10.3KB +608B 4.1KB 4.1KB 0B
core/TabMenu 51.8KB 52.3KB +579B 10.0KB 10.0KB 0B
core/Table 83.9KB 84.7KB +790B 15.1KB 15.2KB +78B
core/TableCell 75.8KB 76.6KB +886B 14.8KB 14.9KB +78B
core/TableHeaderCell 75.5KB 76.4KB +893B 14.8KB 14.9KB +77B
core/TableSelectionToolbar 52.5KB 53.1KB +601B 11.2KB 11.2KB 0B
core/TextInput 53.7KB 54.3KB +579B 10.5KB 10.5KB 0B
core/Thumbnail 50.8KB 51.4KB +598B 11.0KB 11.0KB 0B
core/TimeInput 86.9KB 124.0KB +37.1KB ⚠️ 13.8KB 13.8KB +92B
core/Timestamp 27.7KB 27.7KB +1B 9.5KB 9.5KB 0B
core/Toast 60.0KB 60.6KB +580B 9.7KB 9.7KB 0B
core/ToggleButton 44.3KB 44.8KB +563B 9.3KB 9.3KB 0B
core/Token 29.7KB 30.3KB +600B 4.5KB 4.5KB 0B
core/Tokenizer 68.8KB 69.5KB +726B 16.5KB 16.6KB +71B
core/TopNav 52.0KB 52.5KB +545B 10.4KB 10.4KB 0B
core/TopNavHeading 54.3KB 54.8KB +557B 9.9KB 9.9KB 0B
core/TopNavItem 9.0KB 9.6KB +605B 3.8KB 3.8KB 0B
core/TopNavMegaMenu 54.3KB 54.9KB +600B 10.8KB 10.8KB 0B
core/TopNavMegaMenuItem 9.1KB 9.7KB +603B 4.1KB 4.1KB 0B
core/TopNavMenu 53.7KB 54.3KB +580B 10.1KB 10.1KB 0B
core/TreeList 32.7KB 33.2KB +581B 4.7KB 4.7KB 0B
core/Typeahead 61.6KB 62.2KB +591B 11.3KB 11.3KB 0B
lab/ChatEmojiPicker 65.2KB 65.8KB +547B 773B 773B 0B
lab/ChatReactionBar 65.8KB 66.3KB +530B 1.1KB 1.1KB 0B
lab/CommentComposer 94.2KB 94.7KB +529B 1.9KB 1.9KB 0B
lab/CommentPin 47.5KB 48.1KB +535B 1.2KB 1.2KB 0B
lab/CommentThread 216.0KB 216.8KB +777B 2.4KB 2.4KB 0B
lab/Comments 220.6KB 221.3KB +701B 2.5KB 2.5KB 0B
lab/DiffViewer 45.7KB 46.3KB +602B 2.1KB 2.1KB 0B
lab/EmojiPicker 63.1KB 63.6KB +575B 722B 722B 0B
lab/ListInput 75.3KB 75.5KB +206B 1.6KB 1.6KB 0B
lab/MobilePowerSearch 158.2KB 195.1KB +36.9KB ⚠️ 1.4KB 1.4KB 0B
lab/MobileTokenizer 91.2KB 128.2KB +37.0KB ⚠️ 775B 775B 0B
lab/Schedule 59.9KB 60.5KB +645B 3.9KB 3.9KB 0B
lab/TourStep 55.4KB 56.0KB +560B 590B 590B 0B
lab/TransferList 66.9KB 67.4KB +545B 1.7KB 1.7KB 0B
lab/TransferListSelector 72.4KB 73.0KB +599B 1.9KB 1.9KB 0B
richtext/RichTextEditor N/A 271.4KB N/A N/A 2.6KB N/A
richtext/RichTextEditorToolbar N/A 213.4KB N/A N/A 454B N/A
richtext/RichTextView N/A 251.9KB N/A N/A 2.3KB N/A

Sizes are gzip. Import counts the JavaScript the import loads eagerly; CSS counts the package stylesheet rules referenced by the modules it can load from its own package, lazily loaded ones included.

⚠️ Touch-only size budget

These components grew past the touch-only budget (2 KB gzip JavaScript or 1 KB gzip CSS per component). If the growth runs only on a coarse pointer, load its JavaScript lazily so the import does not carry it, or justify the cost in the pull request description; CSS stays in the package stylesheet, so justify it.

Component JavaScript CSS
core/BottomSheet +37.1KB ⚠️ +98B
core/DateInput +37.0KB ⚠️ +85B
core/DateTimeInput +36.8KB ⚠️ +89B
core/PowerSearch +36.8KB ⚠️ +101B
core/TimeInput +37.1KB ⚠️ +92B
lab/MobilePowerSearch +36.9KB ⚠️ 0B
lab/MobileTokenizer +37.0KB ⚠️ 0B

Bundle Size Summary

Gzip figures measure each package's entry file, not the code an import pulls in.

Package Entry (ESM) Entry gzip before Entry gzip after Delta
@astryxdesign/core 4.9KB 1.2KB 1.2KB 0B
@astryxdesign/lab 4.6KB 1.9KB 1.9KB 0B
Package stylesheet Gzip before Gzip after Delta
@astryxdesign/core 34.6KB 34.7KB +94B
@astryxdesign/lab 11.1KB 11.1KB 0B

Accessibility Audit

Status: No accessibility violations detected.

Visual Regression

55 of 502 shot(s) changed.

A change here is a question, not a failure: check whether the after is the
picture you intended. Record that review on the PR. Baseline maintenance is an
explicit dispatch of CI; this report never rewrites the baseline or adds a release gate.

component story theme mode pixels
Selector Indicator Space Bottom Sheet Narrow End RTL neutral light 753,933
Selector Indicator Space Bottom Sheet Wide Start neutral light 740,072
RichTextEditor Markdown parity: side by side probe dark 558,840
RichTextEditor Markdown parity: side by side probe light 540,756
Chat Full AI Chat probe light 230,823
Chat Full AI Chat probe dark 229,805
AppShell With Mobile Nav probe light 217,010
AppShell With Mobile Nav probe dark 216,960
Collapsible Dividers probe dark 66,445
Collapsible Dividers probe light 66,445
AppShell Playground neutral dark 65,198
AppShell Playground neutral light 63,788
Chat Default neutral dark 36,304
Chat Default neutral light 35,767
Chat Empty State probe light 23,531
Chat Empty State probe dark 22,622
ChatAutoScroll Scroll Behavior Comparison neutral dark 15,378
ChatAutoScroll Scroll Behavior Comparison neutral light 14,107
Chat With Attachments probe light 13,406
Chat With Attachments probe dark 11,232

and 35 more.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@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 pull request is on hold for a spec decision: the BottomSheet wheel and trackpad pull relies on spec:AST-094 FR43, which is only proposed in #8646, while FR19 on main still keeps gesture recognizers off a fine primary pointer and spec:AST-017 FR59 asks for an owner decision before touch work adds new mouse or trackpad behaviour. An engineering owner needs to land FR43 or an equivalent amendment on main, or identify the existing claim that governs this addition, and records that decision by commenting /approve-spec <full head SHA> on this pull request; the author may do so if they are an engineering owner. Separately, the diff against main is 234 files and 47,300 changed lines because it carries the unmerged #8386 and #8676 stack, so please merge those through their own reviews first, or rebase this branch, so that it contains only its own four files.

[Automated review]

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 27, 2026
vjeux added 4 commits October 27, 2026 08:16
…only moves

Under Reduce Motion on a touch device, the morph treats a path with no
opacity of its own as an entrance on a present and an exit on a
dismissal, so the cross-fade lands it at rest (design:reduced-motion).
An element that stays visible and only moves, such as a sub-menu's
parent card, then cut out and faded in on present, and faded out and
popped back on dismissal, with no way for its caller to say so: the
animator's crossfadeAs names only an entrance or an exit. A present or a
dismissal now takes crossfadeAs: 'move', which passes no cross-fade
direction, so the animator plays its own dip: out, the travel lands,
back in.

The new case does not compile before this change (the option had no
value for a move; an untyped 'move' reached the animator only by
accident) and passes after.
…come from pointer events; a press's selection lock gets what it landed on

Where the host reads fingers from pointer events, onTouchStart returned
before its second-finger check and onPointerDown never ran it, so an
unclaimed one-finger pan could still claim after a second finger landed,
and with claimed touches' moves now cancelled in that mode, it would hold
the fingers of a pinch (spec:AST-094 FR10). And onPointerDown handed the
selection lock the event's retargeted target, the shadow host, so a pen
hold on a control inside an open shadow root left that control out of the
lock, selectable in iOS WebKit. Both fail until the host fixes them.
…s come from; a press's selection lock gets what it landed on

The second-finger check (an unclaimed pan limited to one finger fails, so
the two fingers stay the page's pinch, spec:AST-094 FR10) now runs before
onTouchStart's pointer-mode return, and in onPointerDown as a touch
pointer lands while another finger is down, wherever it lands. And
onPointerDown hands lockSelection the element the press landed on, so a
control inside an open shadow root joins the lock.
…handlers type

UseLongPressHandlers.start takes a point only again, as released: the
per-press tolerance useMenuPress's trigger chooses as its press starts
lives on the internal useLongPressDetector and LongPressDetectorHandlers,
which the hooks entry does not export. useLongPress returns the same
detector, typed as before.
vjeux added 2 commits October 29, 2026 18:02
… animations wrap instead of turning

astracat found that the control self-test's back-and-forth animation turns at 1,600 ms. When a loaded runner starts the cast late enough that the block holds the turnaround, two cast frames straddling it evenly read one position, and the control verdict fails the correct compositor animation: "moved on 6 of the 7 frames the control moved". Both self-tests' compositor animations and their timed rAF loops now wrap from 560 px back to 0, a change on every frame. The pooled case's counted mutants still bounce: they are negatives, and a turn changes their position by a full step.

BusyProof.stepPx's note now describes the step it reads from the judged part's changes, and the file header names pooledBusyProof.

Red first: with the setup stretched so the block holds the turnaround, the previous test fails 7 of 12 Chromium runs ("moved on 5 of the 6" and "6 of the 7 frames the control moved"), and this one passes 12 of 12.
…rol inside an open dialog, leaving its backdrop on the compositor

C17 found that in WebKit the control's top-layer popover, shown above an open modal dialog, takes the dialog's `::backdrop` animation off the compositor. BottomSheet's dim held its value for 155 to 225 ms into the block, then jumped to rest, while the control moved on every frame. `startBusyControl(page, {within})` now mounts the box inside the given element as a plain fixed box, with no popover and no top-layer entry. Its frames still count presented frames, and `raise()` leaves such a box where it is.

The self-test opens a modal dialog whose backdrop dims through a block, and judges the dim's brightness at a point against the control.

Red first: in WebKit at 8 workers, with the top-layer control the dim stalled in 5 of 24 runs, from 43 to 78 ms at the block's start, while the control moved ("17/20 moved, longest stall 76.5 ms at +20 ms"); with `within` it passed 24 of 24. Chromium passed either way.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 2026
The harness README's table is meta#8676's, as on meta#8704.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 30, 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 is on hold for a spec decision: the branch carries #8665's amendment to spec:AST-094 FR41 (a mouse or pen drag that a gesture claims after it moves clears the page's text selection, while a press claimed at its own pointerdown keeps it), which main does not state yet. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner; otherwise the amendment leaves this diff when #8665 lands on its own. The wheel and trackpad pull itself follows FR43 and behaves as described in Chromium, with three quick wheel notches resting the sheet on its half detent. Independently, please land #8386 and #8676 through their own reviews and merge main back in (the diff is 243 files and about 47,900 authored lines around a 350-line change), drop or move the pseudoElement option on the harness's sampleCurve that only its own proofs use, and in the stack replace class PressTracker with a factory, as react-component-runtime INV13 requires.

[Automated review]

export async function sampleCurve(
locator: Locator,
times: readonly number[],
{pseudoElement}: {pseudoElement?: '::before' | '::after'} = {},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nothing in the BottomSheet wheel proofs calls sampleCurve with pseudoElement; its only callers are the two new harness proofs (harness.interaction.browser.spec.ts:1436-1505). Please drop the option, its README row and those proofs, or move them to the pull request whose proof samples a ::before or ::after.

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.

Still a class at this head. INV13 of architecture:react-component-runtime on main keeps classes to the recognizer family (its base, the arena and the host), and its verification fails "a class outside the recognizer family". #8763's createPressTracker would conform once it reaches this branch; this belongs to the stacked pull request that owns press tracking.

Comment on lines +471 to +475
(`spec:AST-017` FR59; DEC-9). A mouse or pen drag that a recognizer claims
takes no new text selection for that drag only. A claim made after the
drag has moved clears the page's selection; a press claimed at its own
pointerdown, before it moves, keeps it. An unclaimed mouse drag keeps its
released 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.

This FR41 amendment, carried from #8665, adds a rule main does not state: a mouse or pen drag that a recognizer claims after it moves clears the page's selection, while FR41 on main says a mouse otherwise keeps its released behavior. It needs an engineering owner's decision, recorded with /approve-spec <full head SHA>, or it can leave this diff with #8665.

@vjeux

vjeux commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. On the two other points:

@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 is on hold for a spec decision: the branch carries #8665's amendment to spec:AST-094 FR41 (a mouse or pen drag that a gesture claims after it moves clears the page's text selection, while a press claimed at its own pointerdown keeps it), which main does not state yet. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner; otherwise the amendment leaves this branch and is decided in #8665. The wheel and trackpad pull itself follows FR43 on main, and independently of that decision these changes remain:

  • Land #8386 and #8676 through their own reviews and merge main, so the diff (50,548 authored lines today) carries only this pull request's 7 files.
  • Drop or move sampleCurve's pseudoElement option and its two harness proofs, which #8360's current head does not carry.
  • In the stack, replace class PressTracker with the createPressTracker factory (#8763), as react-component-runtime INV13 requires.

[Automated review]

Comment on lines +471 to +475
(`spec:AST-017` FR59; DEC-9). A mouse or pen drag that a recognizer claims
takes no new text selection for that drag only. A claim made after the
drag has moved clears the page's selection; a press claimed at its own
pointerdown, before it moves, keeps it. An unclaimed mouse drag keeps its
released 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.

This FR41 amendment, carried from #8665, adds a rule main does not state: a mouse or pen drag that a recognizer claims after it moves clears the page's selection, while a press claimed at its own pointerdown keeps it. It needs an engineering owner's decision (/approve-spec <full head SHA>), or it can leave this branch and be decided in #8665.

export async function sampleCurve(
locator: Locator,
times: readonly number[],
{pseudoElement}: {pseudoElement?: '::before' | '::after'} = {},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nothing in the BottomSheet wheel proofs calls sampleCurve with pseudoElement; its only callers are the two new harness proofs (harness.interaction.browser.spec.ts:1833-1906). #8360's current head does not carry this option, so it is this pull request's own change; please drop it or move it to the pull request whose proof uses 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.

Still a class at this head. INV13 of architecture:react-component-runtime keeps classes to the recognizer family (its base, the arena and the host) and fails "a class outside the recognizer family". #8763's createPressTracker factory would fix it once merged into the stack.

This branch was successfully deployed

1 active deployment
Preview — 651039e7 Deployed Oct 30, 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 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