Fix Studio timeline cutoff with many tracks#535
Conversation
jrusso1020
left a comment
There was a problem hiding this comment.
LGTM — clean fix for the timeline-overflow case.
shouldShowTimelineShortcutHint is a pure function with <= 1 slack for sub-pixel rounding and Number.isFinite guards for unmounted refs. Visibility recomputes via ResizeObserver and an effect on [timelineReady, elements.length, totalH], debounced by requestAnimationFrame and cancelled on unmount. The relative className addition on the outer container is needed for the absolute-positioned hint child to position correctly.
Test in Timeline.test.ts covers the boundary cases (220/220 → show, 220.5/220 → show, 221.5/220 → hide). @hyperframes/studio 276/276 pass locally.
— Review by Rames Jusso
vanceingalls
left a comment
There was a problem hiding this comment.
Staff review: approved.
The fix is scoped to the actual obstruction: make the timeline shell the positioning context, detect vertical overflow, and hide the shortcut hint only when it would compete with scrollable tracks. The pure helper has the right sub-pixel tolerance, and the lifecycle cleanup for the RAF/ResizeObserver path looks sound. I did not find any blocking issues.
Problem
Studio’s timeline could become hard to inspect when a composition had many tracks:
data-track-indexrowsWhat this fixes
Root cause
The timeline rendered the keyboard shortcut hint as an always-visible absolute overlay near the bottom of the visible timeline area. That works for short timelines, but with many tracks the scroll container and the overlay share the same bottom region.
Because the hint did not account for vertical overflow, Studio could scroll the final row into view and then immediately cover part of it with the hint. The canvas also had a small bottom spacer that left the last row close enough to the bottom overlay to make the cutoff visible.
Verification
Local checks
bun run --filter @hyperframes/studio test -- Timeline.test.ts-> 33 tests passbun run --filter @hyperframes/studio typecheckbunx oxlint packages/studio/src/player/components/Timeline.tsx packages/studio/src/player/components/Timeline.test.ts-> 0 warnings, 0 errorsbunx oxfmt --check packages/studio/src/player/components/Timeline.tsx packages/studio/src/player/components/Timeline.test.tsgit diff --checkBrowser verification
packages/studio/data/projects/timeline-scroll-cutoff-repro/index.htmlwith 30 separate timeline tracks.http://127.0.0.1:5173/#project/timeline-scroll-cutoff-repro.agent-browserto open the repro, scroll the timeline to the bottom, and verify the measured state:rowCount: 30scrollTop: 2109lastFullyVisible: truehintVisible: falseartifacts/timeline-scroll-cutoff/after-bottom.png.agent-browseratartifacts/timeline-scroll-cutoff/after-scroll-flow.webm.Notes
packages/studio/data/projects/and intentionally not committed.artifacts/and intentionally not committed.bun run --filter @hyperframes/core build:hyperframes-runtimebefore committing.