You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
perf(llc/frontend): Gantt axis ticks are generated for the whole range with no viewport culling #14769
At zoom: 'day' the step is 1 day and ZOOM_PX_PER_DAY.day is 40 (line 161),
so a multi-year range produces thousands of SVG tick elements, nearly all of
them outside the visible scroll window. Each carries a toLocaleDateString
call as well.
Proposed fix
Clamp the loop to the visible horizontal window (scroll offset + client width,
converted back to ms via the inverse of xForMs) plus a small overscan, and
recompute on scroll. Label formatting then only runs for ticks that render.
Acceptance criteria
Tick count is bounded by the viewport width divided by tick spacing, not
by the data range.
Ticks still appear correctly when scrolling to either end of the range at
every zoom level (day / week / month / quarter).
Test asserts tick count stays bounded for a multi-year range at zoom: 'day'.
Source
Found while reading our own Gantt grid code during docs/research/canvas-grid-rendering-review.md Phase 2. Recorded per the
report-and-fix-every-discovered-problem rule rather than folded into an
unrelated change. Sibling finding in the same file: #14767.
Delivered by #14796, merged into Dev_new_gui as d88b6d8aa.
Closed by hand — PRs here target Dev_new_gui, not the default branch, so the Closes #... keyword never fires. Evidence read from origin/Dev_new_gui, not
from the PR diff.
Axis ticks are culled to the visible window (TICK_OVERSCAN_PX, 400px either
side), driven by a ResizeObserver attached from a watch on the element ref
— .gantt-scroll sits behind v-else and does not exist until a timeline
loads, so an onMounted-only hookup would have observed nothing and left the
fallback permanently engaged while appearing to work.
Two invariants matter more than the culling itself, and both are in base:
The interaction with #14767 is the part worth remembering. Culling is
suspended during a PNG export, or the export would have silently shipped a
chart missing every gridline and date label outside the viewport — a worse
defect than the 1x softness being fixed, and invisible in review, because a
complete PNG and a gutted one both look like "an export happened". There is a
test that counts gridlines at serialisation time via a stubbed XMLSerializer, and another asserting culling is restored after a failed
export.
Activity
mrveiss commentedon Aug 23, 2026
Closed — verified in base
Delivered by #14796, merged into
Dev_new_guiasd88b6d8aa.Closed by hand — PRs here target
Dev_new_gui, not the default branch, so theCloses #...keyword never fires. Evidence read fromorigin/Dev_new_gui, notfrom the PR diff.
Axis ticks are culled to the visible window (
TICK_OVERSCAN_PX, 400px eitherside), driven by a
ResizeObserverattached from awatchon the element ref—
.gantt-scrollsits behindv-elseand does not exist until a timelineloads, so an
onMounted-only hookup would have observed nothing and left thefallback permanently engaged while appearing to work.
Two invariants matter more than the culling itself, and both are in base:
indistinguishable from a chart with no data — the same conflation bug(llc/frontend): board and timeline views render a load failure as a legitimately empty board — no error state, no distinction from 'no work' (from #13993) #14064
records for this view's empty state.
if (from > to)).Added for cluster layout still animates for a reduced-motion user #14806... correction, Gantt axis renders no ticks after a zoom change while scrolled #14799, which found that the
viewWidth > 0guard covered only the unmeasured case while a viewport measured under a
previous
pxPerDayreached an empty axis by a different route. The guard wasnarrower than the invariant its own docstring stated.
The interaction with #14767 is the part worth remembering. Culling is
suspended during a PNG export, or the export would have silently shipped a
chart missing every gridline and date label outside the viewport — a worse
defect than the 1x softness being fixed, and invisible in review, because a
complete PNG and a gutted one both look like "an export happened". There is a
test that counts gridlines at serialisation time via a stubbed
XMLSerializer, and another asserting culling is restored after a failedexport.