aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-03 22:20:54 -0700
committerAdam Soltys <[email protected]>2026-09-03 22:20:54 -0700
commita0de5358b872887d8a448ea7c50569010955e294 (patch)
tree7a285d2c89d4f1acebd996fd67ba84c523718aeb /src
parent570dd4f601d2bab8249f108d2910f8197ade3a0b (diff)
downloadcoinosv3-a0de5358b872887d8a448ea7c50569010955e294.tar.gz
coinosv3-a0de5358b872887d8a448ea7c50569010955e294.zip
The carousel's stutter was the switch render landing mid-glide: a one-frame stall showed up ~150ms into a slide — exactly when the settle timer fired the account switch and rebuilt the history list while the card was still moving. The switch now fires on scrollend (motion truly at rest, card already in place), so its render is invisible; the debounce timers survive only as long fallbacks for browsers without scrollend
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
Diffstat (limited to 'src')
-rw-r--r--src/app.js22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/app.js b/src/app.js
index d13dda7..d75b346 100644
--- a/src/app.js
+++ b/src/app.js
@@ -3433,13 +3433,19 @@ function balanceCard() {
};
return h('div', {
class: 'bal-carousel',
+ // The account switch (and its history-list rebuild) is the heaviest work
+ // the carousel triggers — running it mid-glide dropped a frame and read
+ // as a stutter. It now fires on `scrollend`, i.e. once motion has truly
+ // come to rest and the card is already in place, so the render is
+ // invisible. onScroll keeps only a long fallback for browsers without
+ // scrollend; it never drives the switch on its own during a glide.
+ onScrollend: (e) => { const el = e.currentTarget; clearTimeout(el._settle); settle(el); },
onTouchstart: (e) => { const el = e.currentTarget; el._dragging = true; clearTimeout(el._settle); },
onTouchend: (e) => {
const el = e.currentTarget;
el._dragging = false;
- // momentum/snap scroll events reschedule this; a still release needs it
clearTimeout(el._settle);
- el._settle = setTimeout(() => settle(el), 150);
+ el._settle = setTimeout(() => settle(el), 350); // fallback; scrollend usually wins
},
// Desktop: scroll-snap has no mouse drag, so emulate one — grab the
// strip and pull. Touch keeps the native pan (pointerType check);
@@ -3514,10 +3520,11 @@ function balanceCard() {
el.addEventListener('scrollend', restore, { once: true });
clearTimeout(el._snapT);
el._snapT = setTimeout(restore, 700);
- // the glide's own scroll events reschedule this; a release already
- // at rest on the target needs the switch to fire regardless
+ // the account switch waits for scrollend (onScrollend on the strip)
+ // so its render never lands mid-glide; this is only the fallback for
+ // browsers without scrollend, kept long so scrollend wins normally
clearTimeout(el._settle);
- el._settle = setTimeout(() => settle(el), 150);
+ el._settle = setTimeout(() => settle(el), 500);
};
window.addEventListener('pointermove', mv);
window.addEventListener('pointerup', up);
@@ -3525,8 +3532,11 @@ function balanceCard() {
onScroll: (e) => {
const el = e.target;
el._lastScroll = Date.now();
+ // scrollend drives the switch; this long debounce only covers browsers
+ // that lack it, and is kept well clear of a glide's duration so it
+ // never fires mid-motion
clearTimeout(el._settle);
- el._settle = setTimeout(() => settle(el), 120);
+ el._settle = setTimeout(() => settle(el), 400);
},
}, ORDER2.map((v) => h('div', {
class: 'card balance bal-slide',