Restore native scrolling and reliable recognition; add feel tests
The previous round regressed the demo against main: dropped frames while a finger drags, and swipes ignored when they start imperfectly. Frame drops: hosts used touch-action: manipulation plus a blocking touchmove listener, so Chrome waited for JavaScript on every touch move (~30% of frames over 20ms in a drag, p95 28ms). Hosts again use per-axis touch-action like main (pan-y for horizontal gestures, and so on), and attach no touch listener. Flaky recognition: an irreversible decision after 6px dropped swipes with a wobbly or backward start. Recognition again measures from the pointer-down point until the pointer lifts, as on main. Scrolling beside gestures, natively: - .from.scrollEdge() uses direction-specific touch-action while its scroller is at the edge (pan-x pan-down for drag-down at the top), the pull-to-refresh pattern from the Pointer Events spec. A passive scroll listener keeps it current; no touch handling blocks the browser. - Where directional values are unsupported (Safari), scroll-edge gestures alone fall back to claiming touches at the browser's first cancelable touchmove. - Hosts publish touch-action as --nvo-touch-action and the stylesheet applies it to descendants, so nested scroll containers keep it and horizontal swipes over lists are not cancelled. Ignored subtrees get touch-action: auto back. - Bindings gain listeners and ref (spread on the host); the components use them. Feel tests (npm run test:feel): Chromium with emulated touch checks recognition on ten human-like traces, frame pacing budgets while dragging (p95 <= 20ms, <= 5% over 20ms) for a swipe and a scroll-edge dismiss, and the behaviour checks. Against the previous code they fail on exactly the reported regressions; now 23/23 pass. On the demo, all traces match main and drag frame pacing matches or beats it. Commit thresholds are unchanged (0.25 distance, 0.2 flick). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Faarh2Ts6StJPcz2mRiHiR
This commit is contained in:
@@ -241,7 +241,7 @@ describe("reactive gesture props", () => {
|
||||
const rightward = gesture.to.right().navigate(toTarget).animate(motion);
|
||||
const current = shallowRef(leftward);
|
||||
const { scene, host } = await mount(gestureHost(() => current.value));
|
||||
expect(host.style.touchAction).toBe("manipulation");
|
||||
expect(host.style.touchAction).toBe("pan-y");
|
||||
|
||||
// Swap mid-gesture: the drag in progress keeps the leftward definition.
|
||||
host.dispatchEvent(pointer("pointerdown", 180, 0));
|
||||
@@ -295,14 +295,14 @@ describe("reactive gesture props", () => {
|
||||
),
|
||||
});
|
||||
const { scene, host } = await mount(Root);
|
||||
expect(host.style.touchAction).toBe("manipulation");
|
||||
expect(host.style.touchAction).toBe("pan-y");
|
||||
|
||||
list.value = [
|
||||
...list.value,
|
||||
gesture.to.down().navigate(toTarget).animate(motion),
|
||||
];
|
||||
await nextTick();
|
||||
expect(host.style.touchAction).toBe("manipulation");
|
||||
expect(host.style.touchAction).toBe("none");
|
||||
|
||||
host.dispatchEvent(
|
||||
Object.assign(pointer("pointerdown", 100, 0), { clientY: 0 }),
|
||||
|
||||
Reference in New Issue
Block a user