fix(traces): rework Timeline tab — clamping/NaN/perf fixes + navigation UX#252
Merged
Conversation
…er perf + Tier1/2 UX Bug fixes: - clampViewport rewritten: right-then-left edge clamping (no re-violation on oversized windows), centered branch when the window exceeds the padded trace, NaN/Infinity input guards - SET_VIEWPORT now clamps inside the reducer, so minimap pan/resize/jump can no longer drag the viewport off the trace and blank the body - zero-duration traces get a 1ms synthetic window (kills minimap/axis NaN styles); default viewport built through clampViewport so the min-width floor holds at first paint - tooltip + crosshair positions are ref/rAF-driven — mousemove inside one span no longer re-renders the whole timeline - timeline keys stopPropagation so app-global hotkeys (D/F/T/?) don't also fire; keys typed into the search input no longer drive the timeline UX (patterns from Jaeger/Grafana, Sentry, Perfetto, Chrome DevTools): - animated viewport: easeOutSine tween on keyboard + programmatic zooms; direct gestures stay instant and cancel in-flight animations - W/S cursor-anchored zoom, A/D pan, shift-fast variants, F fit span/trace, ? shortcut sheet - span bars: clipping chevrons when a bar extends off-view, viewport-pinned labels for clipped-left bars (px indent), outside name·duration labels for small bars, label gating by visible width - minimap: drag-on-empty reframes with preview-then-commit, click jumps, double-click fits, hover guide with time readout, errors brighter and on top, depth pitch scales with trace depth, resize-edge cursor affordances - search: Enter/⇧Enter cycles matches with k/n counter + focus ring - crosshair time readout; pointer-events disabled on rows during scroll bursts Tests: reducer suite was already failing (stale proportional-floor expectations); fixed and extended with boundary/degenerate/NaN coverage (15 pass). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
Your Pullfrog Router balance is exhausted. You have a card on file but auto-reload is disabled, so runs paused once your balance went past the overdraft buffer. Top up balance → · Enable auto-reload →
|
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.

What
Two passes over the trace Timeline tab (
packages/ui/src/components/traces/), prompted by it being buggy and rough to use.Bug fixes
clampViewportrewritten — right-then-left edge clamping so an oversized window can't re-violate the opposite edge; windows wider than the padded trace get centered; NaN/Infinity inputs recover to a sane window.SET_VIEWPORTclamps inside the reducer — the minimap could previously drag/resize the viewport completely off the trace (negative / >100% rects, empty body). All viewport paths now share one clamp.clampViewportso the min-width floor applies at first paint.stopPropagationso app-global hotkeys (Dtime picker,Ffilter,?help,Ttheme) don't also fire while the timeline is focused; keys typed into the span search no longer drive the timeline.Navigation & orientation UX
Patterns adopted from Jaeger/Grafana, Sentry's trace-view rewrite, Perfetto, and Chrome DevTools:
F, Fit); wheel/drag gestures stay instant and cancel in-flight animations.W/Scursor-anchored zoom,A/Dpan,⇧fast variants,Ffit focused/selected span (else whole trace),?shortcut sheet.‹/›chevrons when a bar continues off-view; clipped-left bars keep their label pinned to the visible edge (px indent — CSS % padding resolves against the parent cell, which was silently hiding labels); small bars get an outsidename · durationlabel on the roomier side; label gating uses visible width, not total bar width.+offsettime readout; error spans brighter and painted on top; depth pitch scales with trace depth instead of piling deep spans on the bottom row.Enter/⇧Entercycles matches with ak/ncounter, focusing + scrolling each match into view.pointer-events: noneon rows during scroll bursts, deadstickyremoved from the time axis.Tests
The reducer suite was already failing on main (2/8 — stale expectations from a removed proportional zoom floor). Fixed those and added coverage for SET_VIEWPORT clamping, degenerate/zero-duration traces, NaN/Infinity inputs, and the oversized-window invariant — 15/15 pass (
packages/ui,bunx vitest run src/components/traces/__tests__/timeline-reducer.test.ts).Verification
bun typecheckclean across the repo (32/32 turbo tasks).NaN/Infinityinline styles; wheel zoom anchors under the cursor;d/f/?no longer trigger the global hotkeys; search cycles 1/6→2/6→1/6 with focus ring.Reviewer notes
useTimelineInteractionsnow returnscrosshairRef/dragMode/getCursorTimeMsinstead ofcrosshairX/isDragging-only; the crosshair div is always mounted and driven imperatively.SET_VIEWPORTper frame — visible-row re-renders during a 120–220 ms tween, same cost profile as an ordinary drag-pan.🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.