fix(web): finish banner loop reset without rAF

Settle the wrapping carousel from resetting to idle with rAF plus a
short timeout fallback so loop clones unmount even when animation frames
are delayed.
This commit is contained in:
CodingOnStar 2026-08-31 20:08:32 +08:00
parent 6864ba33cd
commit 5dec7c76d4
3 changed files with 16 additions and 8 deletions

View File

@ -2607,11 +2607,6 @@
"count": 1
}
},
"web/app/components/plugins/marketplace/utils.ts": {
"no-unused-vars": {
"count": 1
}
},
"web/app/components/plugins/plugin-auth/authorized/index.tsx": {
"no-restricted-imports": {
"count": 1

View File

@ -261,7 +261,9 @@ describe('Marketplace home trending layout', () => {
expect(track.style.transform).toContain('-300%')
expect(track.querySelector('[data-carousel-loop-clone]')).toBeInTheDocument()
await new Promise((resolve) => setTimeout(resolve, 450))
await expect
.poll(() => track.getAttribute('data-carousel-loop-phase'), { timeout: 1000 })
.toBe('idle')
expect(screen.getByRole('button', { name: 'First banner' }).element()).toHaveAttribute(
'aria-current',

View File

@ -140,8 +140,19 @@ function HomeTrending({
useEffect(() => {
if (loopPhase !== 'resetting') return
const frame = window.requestAnimationFrame(() => setLoopPhase('idle'))
return () => window.cancelAnimationFrame(frame)
let settled = false
const settle = () => {
if (settled) return
settled = true
setLoopPhase('idle')
}
const frame = window.requestAnimationFrame(settle)
const timeout = window.setTimeout(settle, 50)
return () => {
window.cancelAnimationFrame(frame)
window.clearTimeout(timeout)
}
}, [loopPhase])
useEffect(