Repository navigation
Conversation
…s pending waitForAnimation and watch.started() left pending animations (no start time yet) out of the running set, so an earlier animation that had finished answered for the one the action started. A pending animation in scope now keeps the wait going. Self-test: a short animation ends, then a longer one starts; the wait returns the longer one (it returned the 40 ms one before). The README and JSDoc say how a mid-run reverse or replay is misread. Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
…ase is one handle, and REDUCED_TRANSITION keeps createAnimator's docs
- attach rebuilt only channels away from identity, so an identity the
animator held inline over a stylesheet that differs (set({opacity: 1}) over
opacity 0) was never written on the node that replaced the element; the
new node showed 0 while get() read 1. The held identities now carry through
a detach to the next node.
- decay under Reduce Motion with one axis past an edge and another coasting
returned a handle that covered only the coasting axis; stop() left the
cross-fade to land. The handle now covers both calls.
- REDUCED_TRANSITION moves above createAnimator's doc comment.
Storybook's highlight module scans the page on every insertion in WebKit as in Chromium, so the self-test now counts the insertion's getComputedStyle calls in both engines; only Chromium's trace counts the style recalculations they force. It no longer serves Storybook for an engine it skips.
…handle for a mixed release); decay's Reduce Motion docs - attach(): #8055's held identities, plus a pseudo-element's: its identity hold (a static animation the attach cancels) is held again on the next node; a borrowed opacity is never held. Test: a ::backdrop's hold follows a node replacement. - decay(): #8055's single handle for a release with one axis past an edge, with `started` covering both calls. Under this layer's plan a stop finishes the cross-fade and lands that axis at once, while invisible, so #8055's test checks that nothing moves after the stop. - Docs: the header, decay()'s and MotionCurve's comments, the motion README and the changeset now say that a curve marked isTransition (a coast's spring back from past an edge) plays through the Reduce Motion policy: a cross-fade on a coarse pointer, at once elsewhere.
…e animations Inside a trace, waitForRest waits on timers for each animation's scheduled end. A scroll- or view-timeline animation (DateInput's wheel rows) has none: its time is a percentage, the wait came out NaN, and the timer re-armed with no delay until the deadline, where the untraced wait rests. It now skips animations that are not on the document timeline, as holdAnimations does. Self-test: a scroll-timeline row inside a trace; it rejected at the deadline before (Chromium, 3x repeat pass).
…t moved frame, and the harness's waits run on the real timers
With a compositor record, the moved criterion counted every compositor
frame in the judged part, but only a gap between two moved frames can be
credited to the compositor, so the frames before the first and after the
last moved frame read as misses: at one screencast frame in six, a
composited animation failed in 5 of 7 runs, where the same frames passed
without the record. The criterion now counts the compositor's frames from
the first to the last moved frame; the gaps before and after are the stall
check's, which already measures the window's edges.
blockMainThread(..., {during}) and sampleRects waited on the page's own
requestAnimationFrame and setTimeout, which freezeTimers holds, so neither
settled under a frozen timer gate, though the harness's own waits are
documented as not held. They now run on the gate's real frame and timeout
(the gate exposes its real setTimeout too). A unit case at one frame in six
and a self-test under a frozen gate fail on the previous code.
…up a wait waitForAnimation and watch.started() counted a scroll- or view-timeline animation (DateInput's wheel rows) as running; it never progresses on its own, so the wait never answered with the animation that finished and rejected at its timeout. Only document-timeline animations count now, as for holdAnimations. Self-test: a scroll-timeline row beside a short animation that ends; it rejected before (Chromium, 3x repeat pass). The installCurveEnd doc comment sits above installCurveEnd again. Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
…s this layer has, and coast says a transition lands at once on a fine pointer
…ator's browser proofs
… pointer); the changeset says the same animator.test.ts keeps this layer's header (no compositor browser spec in this layer). The changeset now says decay sends a spring back from past an edge through the Reduce Motion policy: a cross-fade on a coarse pointer, at once elsewhere.
…side a scroll view The press profiles' README said a cell's highlight always waits the content-touch delay. PressTracker waits it inside a scroll view and lights at once outside one (spec:AST-094 FR11), as its own header says; the README now says so too.
What one call becomes under Reduce Motion (an opacity-only cross-fade whose travel lands while the element is transparent, or everything at once; a dip on a borrowed stylesheet opacity) moves from createAnimator's closure to reducedMotionPlan.ts, a pure planner that reads the animator through a view and returns the plan; the animator turns the plan into its segments and runs the landings. No behavior change: the animator's tests pass unchanged, and the planner has its own. Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
…ed pull requests This pull request keeps the animator's Reduce Motion plan (now its own planner module), the browser-set start of a call from rest, promotion, atRest, rebase and animatorFor. Two features it carried move up the stack, each with its own tests and changeset: - play(curves), baking any closed-form curve like a spring; - driving a pseudo-element (a dialog's ::backdrop). The changeset is split the same way. Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
play(curves) bakes any curve given as value and velocity functions of time (a spring chasing a moving target from solveSpringTowardRamp, a fitted UIKit curve) exactly like a spring: presentation values, velocities, stop, finished and the shared clock work the same, a later animate starts from the curve's value and velocity, and under Reduce Motion a curve that moves is travel the policy replaces. Tests and a changeset of its own. Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
createAnimator(element, {pseudoElement: '::backdrop'}) animates a
pseudo-element: with no inline style, a static filling animation holds
its value after a curve ends and after set; a custom property on its host
promotes it; a Reduce Motion dip borrows and hands back the
pseudo-element's own opacity, and its holds follow a node replacement.
animatorFor keeps one animator per element and pseudo-element. Tests and
a changeset of its own.
Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
…ot the page's frames around it "a harness read inside a trace is not the page's long task…" also asserted that no long task started anywhere in the read's window. On CI's runner each frame of the fixture's 1,200 running rows took 51-54 ms, the page's own long tasks, and failed it; at 4x CPU locally they take 126-220 ms. The read itself was set apart correctly. The test now asserts the read's own classification, and removes the rows before the timer, click and direct-call windows, so each holds only its own work. It passes at 4x CPU, where the previous assertion failed.
…ter the browser takes the touch A host that stopped feeding the finger at the takeover and still delivered the lift would have passed. Each transition now records the list's scrollTop, and the test expects a 'changed' while the list is scrolled (spec:AST-094 FR20: it follows the scroll to the lift).
|
The lint job's |
CI's lint rejected the three Array<T> types the previous commit added (@typescript-eslint/array-type); the test now names its record once (WatchTransition) and reuses it.
There was a problem hiding this comment.
Requesting changes. The watcher itself (claimsTouches: false) follows spec:AST-094 FR11, FR15, FR18, FR19, FR20 and DEC-7, and its real-touch browser case now checks that it keeps reporting moves after the browser takes the touch. Against main, though, this pull request carries 20,634 authored lines, all but the watcher's 525 from the open #8315 line, and it conflicts with main in packages/core/src/motion/animator.ts, so no CI test has run on this head. Please land #8315 and its predecessors and merge main, or base this pull request on a branch in this repository that holds #8315's head, so the diff is the eight-file watcher.
- For the stack's own pull requests: the screen-edge pan decides at 10 px inside its band on a wide view (
ScreenEdgePanGestureRecognizer.ts:117-125) against FR18's 15 px, and the fine-pointer action group cites afamily:action-groupsFR5 that has no record onmain.
[Automated review]
|
The arena resets a recognizer to |
…t reads its end before the arena's reset) into facebook#8336
…s watcher test fixed)
and the meta#8589 watcher-test fix) into c24-8147-base
Depends on #8315 (and its predecessors); review this pull request's own commit (
feat(gestures): a recognizer created with claimsTouches: false is a watcher), about 210 lines over #8315's head.Split out of #8336, which keeps the gesture host's ownership changes.
User need
Some touch behavior only follows the person's scroll and never takes the touch: a tab bar that minimizes while the page scrolls down, a header that collapses. It has to see the finger without delaying the scroll, without stopping another recognizer, and without cancelling a press or click under it.
Problem and solution fit
claimsTouches: falsemakes a recognizer a watcher: it never claims, so its element gets only passive listeners and a scroll never waits for it.spec:AST-094FR15 now states for watchers (spec(AST-094): FR15 exempts watchers from recognizer exclusivity (DEC-7) #8517).touch-action: it restricts no scroll (FR20, DEC-7).Current specification
spec:AST-094FR11, FR15, FR19, FR20, DEC-7.Public delta and caller burden
None: an internal recognizer option, not exported from the package entry point; the changeset is
[chore].Design and alternatives
Evidence
watcherRecognizer.test.ts): runs alongside a claiming pan on the same touch and claims nothing; cancels no press under it; follows a touch the browser took for a scroll until the lift; gets only passive touchmove listeners; writes notouch-actionfor its direction.Writing rubric results
No record text of its own: AST-094 FR15's watcher exemption is on
main(#8517); R1–R6: none.Scope