feat: allow scroll to zoom and panning to trace waterfall viewer#1843
feat: allow scroll to zoom and panning to trace waterfall viewer#1843kodiakhq[bot] merged 5 commits intomainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
Claude finished @karl-power's task in 22s —— View job PR Review✅ No critical issues found. A few minor observations:
|
1db0067 to
aad9127
Compare
|
Claude finished @karl-power's task in 1m 6s —— View job PR Review✅ No critical bugs. Two items worth addressing:
|
E2E Test Results✅ All tests passed • 86 passed • 3 skipped • 961s
Tests ran across 4 shards in parallel. |
aad9127 to
709d75c
Compare
There was a problem hiding this comment.
Stale comment
Code Review
Overall this is a clean refactor — moving
scale/zoom state internals and adopting modern pointer-event patterns. A couple of things worth fixing:
⚠️ Missingpointercancelhandler inuseDrag.ts→ If the browser cancels a pointer event (OS gesture, window blur during drag, touch interruption),pointerupnever fires. TheabortController.abort()won't be called, leavinguserSelect: 'none'permanently stuck on the element (preventing text selection until page reload) and thepointermovelistener orphaned ondocument. Fix by also aborting onpointercancel:document.addEventListener('pointercancel', e => { abortController.abort(); onDragEnd?.(e); }, { signal: abortController.signal });
⚠️ Zoom hint is hardcoded always-visible → The<Kbd>⌘/Ctrl</Kbd> + <Kbd>scroll</Kbd> to zoomhint is unconditionally rendered insideTimelineChartwith no prop to hide it. The component is general-purpose (used byDBTraceWaterfallCharttoday, potentially others), but the hint is now baked into the internals. If zoom is always enabled this is fine, but worth at minimum anshowZoomHintprop or moving the hint to the call site inDBTraceWaterfallChart.✅
useStableCallback+AbortController-baseduseDragare well-implemented patterns.✅ Fixing the
useEffect(() => { ... })(no deps) →useEffect(..., [onWheel])is a correct bug fix — the old code re-registered the wheel listener on every render.✅
DBHighlightedAttributesListguard (highlightedAttributeValues?.length > 0) is a safe improvement.
709d75c to
bbbaa88
Compare
There was a problem hiding this comment.
Stale comment
Code Review
Good overall implementation — clean hook extraction, proper cleanup with
AbortController, and solid use ofuseStableCallback. A few issues worth addressing:
⚠️ Horizontal scroll propagates to parent containers → InonWheel,e.preventDefault()is only called formetaKey/ctrlKey(zoom), but not when handlingdeltaX. The wheel listener is{ passive: false }, sopreventDefault()is available — but without calling it for horizontal scroll, scroll events bubble up and any scrollable ancestor will also scroll simultaneously. Addif (deltaX !== 0) e.preventDefault()before updating offset withdeltaX.
⚠️ Zoom has no upper bound →Math.max(v + -deltaY * 0.01, 1)clamps at minimum scale=1 but allows unbounded zoom-in. A user could zoom in to the point where the timeline is unusable. Add an upper clamp, e.g.Math.min(..., 100).
⚠️ Zoom sensitivity is inconsistent across input devices →deltaY * 0.01means a standard mouse wheel (typicallydeltaY=120per notch) produces a1.2scale jump per click — very aggressive. Trackpads produce fractional deltas so they feel smooth. Consider normalizing delta magnitude or using a smaller multiplier like0.005.
There was a problem hiding this comment.
Code Review
Overall this is a clean refactor — moving scale/offset state internally, adopting AbortController-based drag cleanup, and extracting reusable hooks are all improvements.
Issues to address before merge:
-
⚠️ No maximum zoom level inTimelineChart.tsx→setScale(v => Math.max(v + -deltaY * 0.01, 1))has no upper bound. Extreme zoom levels (e.g. scale=1000) make panning hypersensitive and individual spans vanish. Add a cap:Math.min(Math.max(v + -deltaY * 0.01, 1), 100)or similar. -
⚠️ MissingsetPointerCaptureinuseDrag.ts→ Withoute.currentTarget.setPointerCapture(e.pointerId), if the pointer leaves the browser window during a drag (e.g., dragging into OS chrome and releasing),pointerupmay never fire ondocument, leaving theAbortController's listeners attached until the next drag starts. Adde.currentTarget.setPointerCapture(e.pointerId)inonPointerDown. -
ℹ️ Zoom hint always visible → The
⌘/Ctrl + scroll to zoomhint renders permanently above the timeline. Consider showing it only on hover or as a tooltip to reduce visual clutter.
✅ No critical bugs or security issues found. The useStableCallback pattern, AbortController-based cleanup in useDrag, useLayoutEffect for scale offset sync, and highlightedAttributeValues?.length > 0 guard are all solid improvements.
fef4cba to
4189e3a
Compare
PR Review
✅ The core implementation is clean — |
4189e3a to
5542b4a
Compare
pulpdrew
left a comment
There was a problem hiding this comment.
LGTM, this is a nice improvement. Please add a changeset


Summary
Closes HDX-3527
cmdorctrlkey and scrolling in or out, adds hint to user that this is possible.Screenshots or video
Screen.Recording.2026-03-09.at.11.54.55.mov
How to test locally or on Vercel