Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/pager-resize-settle-retarget.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[fix] Carousel paging: a row that resizes while it settles no longer stops at once or runs back to an earlier page. The settle plays on at its speed, to the last page when it was heading there, and otherwise to the page nearest where it was heading. It ends on that page with no step when it goes back to native scrolling. A resize that leaves the row past its new last page still lands it on that page at once.

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.

Non-blocking: "lands it on that page" names the new last page, but the pager lands a past-the-end row on its target (usePager.ts:1170). With five fixed-width views widened from 300 to 450 px while settling from the end toward the fourth view, the row lands at once on 932 px, not on the new last page at 1082 px. Suggested: "A resize that leaves the row past its new last page still lands it at once on the page it was heading for." This corrects the wording the last review suggested.


@vjeux
13 changes: 10 additions & 3 deletions docs/specs/AST-094-touch-presentations/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,13 @@ a measured, sourced difference exists.
velocity to the settle. The floor is a guess inside the measured bracket
(UIKit zeroes steady releases at 175 and 200 pt/s and keeps 249 pt/s, iOS
26.2 simulator, 2026-10-23) until a measurement replaces it (FR2). A page
change during a drag starts from rest (DEC-25). A finger or a pen that lands
on a pager's settle after a release never reaches the pager's content: no
press feedback and no click. UIKit's content took none of 30 such touches
change during a drag starts from rest (DEC-25). A resize during a settle
retargets it. When the spacings between pages all scale by one ratio, the
settle keeps its page and its fraction of a page. Otherwise a settle toward
the last page ends on the last page. Any other ends on the page nearest its
target's offset, a tie going the way it moves. A finger or a pen that
lands on a pager's settle after a release never reaches the pager's content:
no press feedback and no click. UIKit's content took none of 30 such touches
(iOS 26.2 simulator, 2026-11-06). A finger or a pen that lands on a pager's
`goTo` move stops it at the touch, and the lift settles on the nearest page;
the content still takes the tap. UIKit's animated `setContentOffset` stopped 2
Expand Down Expand Up @@ -1034,6 +1038,8 @@ under a finger, and a mouse follows `module:DropdownMenu/useMenuPress` FR3 and
- FR6 gap: under a starved compositor, Chromium can show a frame 40 to 60 ms
after the main-thread frame that builds it. A retarget then first shows that
far into its curve: up to 6.5 px on a loaded Switch.
- FR6 gap: a resize during a settle drops its velocity when it leaves the row
past its new last page. The row lands on its target at once.
- Consumer docs: none until a component ships its touch presentation; each
component documents its own, including the `presentation` value that keeps
the released surface (FR25).
Expand Down Expand Up @@ -1077,6 +1083,7 @@ Motion that FR45 moves, by component. Each component's record carries its own li
| FR6 pager | Unit and browser tests of a pager's settle start | releases just under and over 225 pt/s; a catch mid-settle; a programmatic page change mid-settle | a release under the floor whose settle starts moving, a release over it whose settle starts from rest, a catch that loses the on-screen velocity, or a programmatic page change mid-settle that starts from rest fails; a page change during a drag starts from rest |
| FR6 starved | Switch frame proofs on a starved main thread (4 workers on 2 cores); unit tests of a retarget on a settle tail and a rebase toward a new rest | a second tap mid-travel, with frames read late or its lift handled 100 ms late; a first frame committed late; a retarget once the thumb is still; a value change mid-slide, whose rebase moves the travel whole | a jump out of a thumb that is still fails; a value change mid-slide shows no step |
| FR6 late commit | A browser test of a retarget behind a 200 ms block; unit tests of a retarget whose frame comes late | a retarget made in a task, and one made in a frame callback of the page, before a 200 ms block; a frame within 34 ms of the call; a velocity the call hands the spring; a hidden page; two properties, and two animators, before one late frame; retargets on two animators in one callback | a step at the frame that commits a retarget fails; a retarget whose frame comes within 34 ms keeps the call's own clock; a retarget made in a frame callback of the page that shows its new curve in any frame but the next fails; a late frame that drops a handed velocity fails; a hidden page's retarget that never finishes fails; a later call before a late frame that keeps its own clock fails; two animators' retargets in one callback on different clocks fail |
| FR6 resize | Unit and browser tests of a resize during a pager's settle | a narrowing that renumbers the pages mid-settle; a widening and a narrowing of pages as wide as the row, mid-settle and mid-drag; a rotation of pages with a fixed gap; pages that share a shift; a still finger whose catch spans a resize; a widening that regroups fixed-width views; a tie between two pages (units); a narrowing that splits the last page from the stop before it; a narrowing while a release settles toward the last page, sampled every frame on each settle's own clock | a settle that ends on its old index's new offset, a settle or release on scaled pages that ends on another page or loses its fraction of a page, a regrouping that jumps, a tie that reverses, a settle toward the last page that ends short of the new last page, a split-end settle that rests on the split-off stop, or a frame after that narrowing more than 1 px from the paging integrator's curve fails. The curve runs from where the settle shows as the new one starts, at its velocity then, to the new last page. The first frame after the narrowing may still show the settle before it, or the new curve between its start and its clock, where the browser commits it inside that frame |
| FR7, FR8 | Component browser tests and storyboards with and without Reduce Motion | entrance, exit, move; a drag and its lift under Reduce Motion; a tap-, key- and program-started close of a sheet and the Lightbox | a missing exit, any travel, scale or spring under Reduce Motion other than a coast after a throw and its settle at an edge (`design:reduced-motion` DR2), an opacity fade over 200 ms, or a tap-, key- or program-started close of a gesture component on the exit curve instead of its spring, fails |
| FR45 | Browser tests with a mouse, a pen, a trackpad and a finger at each `tempo` bound and each `character`, and with Reduce Motion | a tap, a click, a key and a programmatic change on a Switch, a menu, an alert, a sheet and a ProgressBar under a fine and a coarse pointer; a drag release, a flick and a pinch on a Switch, a Slider, a sheet, a pager and a Lightbox photo under each pointer; a tap that continues as a drag | a tap, click, key or programmatic change in a tap-classified component that plays a measured role or a spring instead of the theme's duration and easing tokens, a touch tap-started move in a gesture or gesture-capable component on a curve instead of its spring, a click, a key or a value change on Switch or SegmentedControl without a touch presentation that leaves the theme's curve, a velocity-carrying release that settles from rest or on a curve, a gesture's spring that ignores `character` or `tempo`, or a part that follows one pointer and not another, fails; the pager's measured settle, which does not yet follow `character`, is a recorded implementation gap |
| FR45 | Component source and token tests for a tap component's motion whose record names no step, with a platform measurement | a small anchored surface (a popover, a menu, a toggle, a row) and a full-screen surface (a Dialog, an AlertDialog), each with its own measurement; a tap component's overlay exit | a token cited as nearest to the measurement in the Storybook theme passes, and a tap component's overlay exit on `--duration-exit` passes; a token chosen by role alone, or nearest at Core's unthemed defaults, fails |
Expand Down
Loading