Skip to content

fix(BorderGlow): cancel the intro sweep on cleanup - #1110

Merged
DavidHDev merged 1 commit into
DavidHDev:mainfrom
Enesuygurs:feat/fix-border-glow-sweep-cleanup
Nov 8, 2026
Merged

DavidHDev merged 1 commit into
DavidHDev:mainfrom
Enesuygurs:feat/fix-border-glow-sweep-cleanup

Conversation

@Enesuygurs

Copy link
Copy Markdown
Contributor

BorderGlow's animated intro sweep is started from a useEffect that has no cleanup, and its animateValue helper never keeps the setTimeout / requestAnimationFrame IDs it creates. So once the sweep starts, nothing can stop it:

  • Unmounting the card during the ~4s sweep leaves the timers and rAF loops running. They keep writing CSS variables to a detached node (CSS variants) or calling setState on an unmounted component (Tailwind variants).
  • Turning animated off doesn't stop the sweep, and the glow stays visible until the sweep finishes.
  • Turning it off and on again within those 4 seconds (e.g. the "Animated Intro" switch on the docs page) runs two sweeps at once. Both write --cursor-angle / --edge-proximity on the same frames, and the old sweep's onEnd then hides the glow halfway through the new one.

animateValue now keeps its timer and frame IDs and returns a cancel function. The effect collects the four sweep phases, and its cleanup cancels them and ends the sweep state (sweep-active class / sweepActive state). The change is applied to all four variants and to their public/r/BorderGlow-*.json registry entries.

Reproduction and validation

I bundled the actual component files (before and after) into a small page, ran it in Chrome, and counted the helper's rAF callbacks. All four variants gave the same results:

Before After
Sweep frame callbacks in the 4.5s after unmounting mid-sweep ~1,240 0
Glow still visible right after animated is turned off yes no
Glow visible midway through a sweep restarted 1s in no (cut by the old sweep) yes
Max sweep callbacks in one frame after re-enabling 4 2
  • ESLint passes for both JS variants. The existing npm run lint failures are in other components and are unchanged.
  • A strict TypeScript check passes for both TS variants.
  • npm run check:prop-docs passes and git diff --check is clean.
  • When the sweep runs normally, its timing, easing and appearance are unchanged.

@DavidHDev DavidHDev left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all four variants and their registry entries. Validated cleanup before delayed phases start, unmount during the sweep, and turning the intro off/on: cleanup leaves no pending animation work or later writes, and a restarted sweep completes without being hidden by the old one. The normal timing is preserved. Looks good, thanks!

@DavidHDev
DavidHDev merged commit f09d248 into DavidHDev:main Nov 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants