Files
gui-video-clipper/chat-summaries/2026-09-22_17-42-fix-resize-waveform-alignment-summary.md
cottongin c90b6765b7 fix: timeline resize regression + dynamic lane alignment
- Remove splitAreaEl dependency from handleResizeMove; use fixed 40-500 clamp
- Add computeLanes() + LaneLayout for dynamic lane height computation
- Update clipRenderer to accept LaneLayout instead of hardcoded constants
- Tighten CONTROLS_HEIGHT (30→22) and CLIP_HEIGHT (30→20) to reduce gaps
- Tighten label baseline offset (14→10) for better waveform-to-tick alignment

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-22 18:15:19 -04:00

2.7 KiB

Fix Resize + Waveform Alignment

Date: 2026-09-22 17:42 Task: Implement the "Fix Resize + Waveform Alignment" plan to fix horizontal resize regression and waveform/lane alignment issues.

Changes Made

1. Resize Regression Fix — src/App.svelte

  • Root cause: After the CSS-grid refactor, handleResizeMove used splitAreaEl.clientHeight as the upper bound. Since .lower-section only contained the resize handle (5px) + timeline pane, totalHeight ≈ timelineHeight + 5, so the clamp Math.min(totalHeight - 20, ...) immediately locked the height.
  • Fix:
    • Removed splitAreaEl state variable.
    • Removed bind:this={splitAreaEl} from the .lower-section div.
    • Simplified handleResizeMove to use a fixed max of 500 (matching the existing keyboard resize handler): Math.max(40, Math.min(500, resizeStartHeight + delta)).

2. Dynamic Lane Layout — src/lib/timeline/renderer.ts

  • Removed fixed lane height constants (THUMB_LANE_HEIGHT, WAVEFORM_LANE_HEIGHT, CONTROLS_LANE_HEIGHT).
  • Added LaneLayout interface and computeLanes(totalHeight) function that dynamically computes lane positions proportionally based on total canvas height.
    • Controls lane: fixed 30px at bottom.
    • Clip lane: fixed 30px above controls.
    • Remaining space split 55/45 between thumbnails and waveform (with minimums of 20px and 15px).
  • Updated drawTimeline to call computeLanes(height) and pass layout to all sub-draw functions.
  • Updated drawTimeTicks to accept LaneLayout and use lanes.controlsY instead of state.height - CONTROLS_LANE_HEIGHT.

3. Clip Renderer Update — src/lib/timeline/clipRenderer.ts

  • Removed hardcoded CLIP_LANE_Y and CLIP_LANE_HEIGHT constants.
  • Updated drawClips and hitTestClip signatures to accept LaneLayout parameter.
  • All clip positioning now uses lanes.clipY and lanes.clipHeight.

4. Timeline Component Update — src/lib/components/Timeline.svelte

  • Imported computeLanes from renderer.
  • Updated hitTestClip call to pass computeLanes(timelineState.height).

Verification

  • npm run check (svelte-check): 0 errors, 0 warnings.

Files Modified

  • src/App.svelte
  • src/lib/timeline/renderer.ts
  • src/lib/timeline/clipRenderer.ts
  • src/lib/components/Timeline.svelte

Lessons Learned

  • When using CSS grid layouts, elements that previously represented the "total space" may now only contain their own children. Relying on clientHeight of such elements for resize calculations breaks — use fixed bounds instead.
  • Dynamic lane computation is preferable to fixed pixel constants because it adapts to any canvas height, preventing gaps or overlaps when the user resizes the timeline.