Fix MarqueeWall reset-on-stop flicker: freeze in place, don't snap to origin#1498
Conversation
… origin [preview:none] Split the single `marqueeActive` flag into a structural gate and a run-gate. Previously one flag controlled both "is this a marquee (clone + transform driver mounted)" and "is the rAF running", so when the per-beat `animate` run-gate flipped false (a stepped deck slide advancing past a wall's beat, or the deck-wide WCAG pause), an effect cleared `track.style.transform` and reset `posRef` to 0 — snapping the track back to its origin. That snap read as a one-frame flicker (visible on company-hub /?slide=8). Now `marqueeMounted` (mode animated + overflows + motion allowed) owns the clone copy, seam gap, will-change, transform-clear, and position reset — it only tears down on a GENUINE static transition (content now fits or reduced-motion). `marqueeActive = marqueeMounted && animate` owns only the engine's rAF. Toggling the run-gate now just stops the loop and freezes the track exactly where it was, resuming at cruise via the persisted velocity envelope — identical to how the existing `nearViewport` gate already behaved. Also fixes the WCAG pause button, which previously snapped every running wall to origin, and keeps FLIP-morph capture accurate for trackId chip walls. Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
Warning Review limit reached
Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
On stepped/animated marquee surfaces, when the marquee stops after already running the track snaps back to its initial position — a one-frame flicker. Reproducible on
company-hub /?slide=8(the AutoFix slide): its core wall animates only on step 1 (animate={s === 1}); advancing past step 1 flipsanimatefalse and the track jumps to origin.Root cause
<MarqueeWall>collapsed two distinct concepts into onemarqueeActiveflag:That single flag gated both the structure (clone copy + transform driver mounted) and the rAF run state. So when the per-beat
animaterun-gate flipped false (a stepped slide advancing, or the deck-wide WCAG pause button), the transform-clear effect firedtrack.style.transform = ''and the layout effect resetposRef = 0— snapping to origin and unmounting the clone. Notably the existingnearViewportgate already did the right thing (stop the rAF without clearing the transform), so pausing just needed to behave the same way.Fix
Split the flag:
marqueeMounted=mode === 'animated' && !reducedMotion && overflows— structural. Owns the clone copy, seam gap,will-change, transform-clear, andposRefreset. Tears down only on a genuine static transition (content now fits, or reduced-motion).marqueeActive=marqueeMounted && animate— run-gate. Owns only the engine'sactive.Toggling the run-gate (step-gate / deck pause / off-screen) now just stops the rAF and freezes the track exactly where it was; the persisted velocity envelope means resume is at cruise, not a 0→speed ramp — identical to the
nearViewportcontract.Side benefits
trackIdchip walls — a paused wall keeps its real offset in the registry instead of zeroing it.Scope & safety
One file (
src/components/ui/marquee-wall.tsx). The otherMarqueeWallconsumers are unaffected:QuickActionWallis a thin wrapper, andCardsStripdrives the engine on a real scroller that never resetsscrollLefton stop. A full audit of the lib, the company-hub deck (FLIP morphs, scroll-pinning, step reveals), and the rest of the hub found no other instance of this reset-on-stop pattern — the deck was already deliberately built to freeze/settle in place.Verification
tsc --noEmitclean.company-hub /?slide=8recommended before the hub pins the release (per-repo convention).Follow-up
Lib-only change → after merge + release, bump the
@flamingo-stack/openframe-frontend-corepin inmulti-platform-hubto pull it into company-hub.🤖 Generated with Claude Code