- 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>
45 lines
2.7 KiB
Markdown
45 lines
2.7 KiB
Markdown
# 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.
|