Redesign beat indicator with cursor and dual target zones#118
Merged
Redesign beat indicator with cursor and dual target zones#118
Conversation
…et zones The beat bar was broken because: - The fill bar + CSS transition added visual lag - The target zone (right:10%, width:15%) didn't match the actual on-beat window (phase > 0.75 || phase < 0.15) - beatPhaseRef was updated via delayed useEffect sync instead of directly in the animation loop Replaced the fill bar with a sweep cursor and dual target zones that accurately reflect the hit window. Removed CSS transitions for frame-precise positioning and added gold glow feedback when the cursor enters the on-beat zone. https://claude.ai/code/session_01JaUmAPTKmyrS7w3Mn32v54
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
React 18's automatic batching of setBeatPhase() inside requestAnimationFrame caused dropped/delayed re-renders — the cursor didn't move on Edge and moved inconsistently on Chrome. Now the rAF loop sets a CSS custom property (--beat-phase) and a data-onbeat attribute directly on the beat bar DOM element, bypassing React reconciliation entirely. The cursor position is driven by CSS calc(var(--beat-phase) * 100%) for frame-precise, re-render-free animation on all browsers. setBeatPhase is still called at ~30fps for Board's fever rainbow effect, but it no longer drives the beat cursor. https://claude.ai/code/session_01JaUmAPTKmyrS7w3Mn32v54
useRhythmVFX() returns a new object on every render (no useMemo). Since vfx was in the beat timer effect's dependency array, each React re-render restarted the timer, resetting lastBeatRef and jumping the beat cursor back to 0. The cursor could only advance ~33ms before being reset — roughly 15% of the bar at 100 BPM. Fix: store vfx in a stable ref (vfxRef) that's updated on every render but doesn't trigger effect re-runs. All vfx.emit() calls now use vfxRef.current.emit(), and vfx is removed from all useCallback/useEffect dependency arrays. https://claude.ai/code/session_01JaUmAPTKmyrS7w3Mn32v54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Redesigned the beat timing indicator bar from a fill-based progress bar to a cursor-based system with dual on-beat target zones. The cursor now sweeps left-to-right across the bar, glowing gold when positioned within the valid hit window (phase 0–15% or 75–100%).
Key Changes
Beat bar UI overhaul: Replaced single
beatFillelement with:beatTargetLeft: Left zone (0–15% phase) marking early on-beat windowbeatTargetRight: Right zone (75–100% phase) marking late on-beat windowbeatCursor: Moving indicator that glows when inside either zoneCursor positioning: Changed from width-based fill to
leftpositioning withtranslateX(-50%)for precise frame-aligned movementVisual feedback: Added gold glow effect (
#FFD700with box-shadow) when cursor enters on-beat zones, improving hit-timing clarityRef ordering fix: In beat phase animation, now updates
beatPhaseRefbeforesetBeatPhaseto ensure ref is current for frame-precise game logic judgmentsStyling refinements:
Component updates: Applied consistent changes across
Rhythmia.tsx,VanillaGame.tsx,tetris.tsx, andGameUI.tsxcomponentImplementation Details
The beat phase cycles 0→1 each beat interval. The on-beat window spans two zones to accommodate both the immediate post-beat moment and the anticipatory pre-beat moment, giving players a more forgiving hit window while maintaining visual clarity about timing.
https://claude.ai/code/session_01JaUmAPTKmyrS7w3Mn32v54