Skip to content

fix(chart): don't render bars without a computed layout position#29

Open
dalley wants to merge 1 commit into
svar-widgets:mainfrom
dalley:fix/skip-unpositioned-bars
Open

fix(chart): don't render bars without a computed layout position#29
dalley wants to merge 1 commit into
svar-widgets:mainfrom
dalley:fix/skip-unpositioned-bars

Conversation

@dalley

@dalley dalley commented Jun 11, 2026

Copy link
Copy Markdown

Fixes #30

Problem

A task that never received a computed layout position still renders a wx-bar element, producing a confusing "ghost bar":

  • When date normalization is skipped — a task with unscheduled: true, or any task without a start date — the layout math leaves $x/$w as NaN.
  • taskStyle() then emits left: "NaNpx", width: "NaNpx"; the browser rejects the invalid declarations.
  • The bar element ends up with only top/height, so it sits at the chart origin and auto-sizes to its label text. To a user this reads as a real (and very wrong) schedule — the bar's apparent "duration" is the pixel length of its own title.

Repro

Add a dateless task to any demo dataset, e.g. in demos/data.js:

{ id: 999, text: 'Dateless task (ghost bar repro)', parent: 0 },

A bar appears at the chart start spanning roughly six "days" — the width of the label.

This is easy to hit from the MIT package: unscheduledTasks is disabled in the store's init(), but normalizeDates still honors the per-task unscheduled flag (and calcDates is a no-op for tasks with no start), so any dateless task paints a ghost bar with no way to opt out.

Fix

Guard the main bar and the baseline element on Number.isFinite() of their computed positions ($x / $x_base). The row still appears in the grid; nothing is painted on the timeline until the task has real coordinates.

!= null is not sufficient — the skipped-normalization path produces NaN, not undefined.

Verification

Ran the demos with the repro task above: before — ghost bar at the origin; after — the grid row is present and the timeline row is empty, while all scheduled bars, milestones, summaries and baselines render unchanged.

🤖 Generated with Claude Code

A task whose date normalization was skipped — an unscheduled task, or any
task without a start date — never gets numeric $x/$w coordinates. The
layout math leaves them NaN, taskStyle() then emits left/width values
like "NaNpx", the browser rejects the invalid declarations, and a ghost
bar renders at the chart origin, auto-sized by its own label text. To a
user this reads as a real (and very wrong) schedule.

Repro: add a task with no start/end to any demo dataset — a bar appears
at the chart start whose 'duration' is the pixel length of its title.

Guard the main bar and the baseline bar on Number.isFinite of their
computed positions: the row still appears in the grid, but nothing is
painted on the timeline until the task has real coordinates.
@dalley dalley marked this pull request as ready for review June 11, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tasks without dates render a ghost bar sized by their label text

1 participant