Frontmatter
| id | 8582 |
| title | Fix TimelineCanvas sync drift by adding debounced final alignment check |
| state | Closed |
| labels | bugai |
| assignees | tobiu |
| createdAt | Jan 13, 2026, 12:18 AM |
| updatedAt | Jan 13, 2026, 12:28 AM |
| githubUrl | https://github.com/neomjs/neo/issues/8582 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Jan 13, 2026, 12:28 AM |
Fix TimelineCanvas sync drift by adding debounced final alignment check
tobiu assigned to @tobiu on Jan 13, 2026, 12:28 AM

tobiu
Jan 13, 2026, 12:28 AM
Input from Gemini 3 Pro:
✦ I have fixed the alignment drift by implementing a robust, debounced final check.
The Fix:
- Intermediate State: The
waitForDomRectmethod insideonTimelineDataLoadworks correctly, but during a CSS animation (like expanding/collapsing the summary), it captures the current animating position, not the final one.- Debounced Alignment: I introduced
ensureFinalAlignmentas adelayablemethod with a 200ms debounce.
- This method re-triggers
onTimelineDataLoadwith the cached records.- Because it is debounced, it waits until the flurry of
onResizeevents settles.- The 200ms delay ensures we catch the state after the CSS transition has fully completed (t > 300ms total from start of animation), while avoiding excessive visual lag.
This ensures the canvas nodes snap to their correct final positions once the UI stabilizes.
tobiu closed this issue on Jan 13, 2026, 12:28 AM
During the expand/collapse animation of the ticket summary,
onResizefires multiple times as expected. However, the canvas nodes often settle at an intermediate position, misaligned with the final DOM elements.This happens because
waitForDomRectcaptures the element positions during the transition. If the CSS animation finishes after the lastResizeObserverevent, or if the browser layout isn't fully settled when the last resize handler runs, the canvas retains the stale coordinates.Resolution:
ensureFinalAlignmenttostatic delayableinTimelineCanvas.mjs(debounce: 100ms).ensureFinalAlignment, callthis.onTimelineDataLoad(this.lastRecords, true).onResize, callthis.ensureFinalAlignment()in addition to the immediate update.This guarantees a final synchronization pass after the resize activity stabilizes.