Found while verifying a premise on #7204. Filed unassigned, not claiming. This is a different defect from #7204: that card is about names being squeezed at 1024px and wider; this one is about dates being absent entirely in a band #7204 never visits.
Measured on origin/main3561bd2ca93b2cd3f7e63616f0c986328c6408ce, packages/plugin-gantt/src/GanttView.tsx.
Symptom
At any viewport from 640px up to 1023px, a gantt task-list row shows neither the Start/End date columns nor the 8/26 → 9/2 sublabel under the title. The row's dates exist in the DOM twice and are painted zero times. No drag and no configuration is needed — it is the default at those widths.
Mechanism — two gates on two different width sources, and they overlap wrong
Both gates are in GanttView.tsx.
Gate 1 — the Start/End columns. Container-driven, in JS:
taskListWidthForContainer(width) -> width under 640: 140 | under 1024: 220 | else 320
showStartEndColumns(taskListWidth) -> taskListWidth >= 280
so at a container width of 640..1023 the default task-list width is 220, and showStartEndColumns(220) is false. The two cells are rendered with hidden plus an inline display: none.
Gate 2 — the date sublabel. Viewport-driven, in the component's own injected style element:
@media (min-width: 640px) {
.gantt-sm-hidden { display: none; }
}
and the sublabel span carries gantt-sm-hidden. Above 640px it is display: none.
Gate 1 reads the container (a ResizeObserver on the gantt root: effectiveWidth = containerWidth || window.innerWidth). Gate 2 reads the viewport (a CSS media query). The two are the same number only when the gantt fills the window. The uncovered band is where gate 1 has already withdrawn the columns and gate 2 has already withdrawn the sublabel.
Measurements
A. Real Chromium 1194 (/opt/pw-browsers/chromium-1194), loading the component's own rendered markup and its own injected style element, reading getComputedStyle(sublabel).display:
| viewport | sublabel display | sublabel client width |
|---|
| 500 | inline | 72.9 |
| 639 | inline | 72.9 |
| 640 | none | 0 |
| 800 | none | 0 |
| 1024 | none | 0 |
| 1440 | none | 0 |
| 1920 | none | 0 |
B. jsdom render of GanttView at container width 800, reading the two Start/End cells of a data row:
w-16 gantt-sm-w20 text-right ... | hidden attr = true | inline display = none (start, "8/26")
w-16 gantt-sm-w20 text-right ... | hidden attr = true | inline display = none (end, "9/2")
and the list header at that width renders only Task Name plus the open-details spacer — the Start and End header captions are gone too.
A and B are the same width, so at 800px both gates are shut simultaneously: no columns, no sublabel.
The band is wider than the default case
Gate 1 keys off the task-list width, not the viewport, and the user can drag the splitter down to TASK_LIST_MIN_W = 160. So the hole also opens at 1024px and above whenever the persisted layout holds a dragged width under 280 — and a dragged width is the only way taskListWidth is ever anything but the three defaults, since there is no prop and no GanttConfigSchema key for it.
There is a mirror-image hole at the other end: a viewport under 640px with the task list dragged wider than 280 satisfies showStartEndColumns, but the columns also carry Tailwind's hidden sm:block, so the viewport keeps them hidden while gantt-sm-hidden is inactive — that one lands the right way up (the sublabel shows).
What is left when both gates shut
Only the bar hover tooltip, which is itself conditional: the tooltip prints Aug 26 → Sep 2only when task.fields is empty. Configure the documented tooltipFields key and the tooltip renders those fields instead, at which point a row's start and end dates are not readable anywhere in the view without opening the detail drawer.
Inline edit is caught by the same gate: the Start/End cells are also where the two type="date" inputs live, so at a task-list width under 280 an inline-editing user can edit the title but cannot see or change the dates.
Suggested directions — maintainer's call, none proposed as decided
- A. Make the sublabel the complement of the columns rather than a separate viewport rule: render it exactly when the Start/End columns are not rendered. Needs care, because "the columns are rendered" is currently the conjunction of a container test and a viewport test.
- B. Move gate 2 off the viewport onto the same container width gate 1 uses, so the two decisions cannot disagree about how wide the gantt is.
- C. Leave both gates and accept the hover tooltip as the fallback — cheapest, but it is hover-only and
tooltipFields defeats it.
Related: #7204 (the same two functions, at 1024px and wider). Fixing this one likely settles the shape question #7204 is currently blocked on, so they probably want to be decided together.
Generated by Claude Code
Found while verifying a premise on #7204. Filed unassigned, not claiming. This is a different defect from #7204: that card is about names being squeezed at 1024px and wider; this one is about dates being absent entirely in a band #7204 never visits.
Measured on
origin/main3561bd2ca93b2cd3f7e63616f0c986328c6408ce,packages/plugin-gantt/src/GanttView.tsx.Symptom
At any viewport from 640px up to 1023px, a gantt task-list row shows neither the Start/End date columns nor the
8/26 → 9/2sublabel under the title. The row's dates exist in the DOM twice and are painted zero times. No drag and no configuration is needed — it is the default at those widths.Mechanism — two gates on two different width sources, and they overlap wrong
Both gates are in
GanttView.tsx.Gate 1 — the Start/End columns. Container-driven, in JS:
so at a container width of 640..1023 the default task-list width is 220, and
showStartEndColumns(220)isfalse. The two cells are rendered withhiddenplus an inlinedisplay: none.Gate 2 — the date sublabel. Viewport-driven, in the component's own injected style element:
and the sublabel span carries
gantt-sm-hidden. Above 640px it isdisplay: none.Gate 1 reads the container (a ResizeObserver on the gantt root:
effectiveWidth = containerWidth || window.innerWidth). Gate 2 reads the viewport (a CSS media query). The two are the same number only when the gantt fills the window. The uncovered band is where gate 1 has already withdrawn the columns and gate 2 has already withdrawn the sublabel.Measurements
A. Real Chromium 1194 (
/opt/pw-browsers/chromium-1194), loading the component's own rendered markup and its own injected style element, readinggetComputedStyle(sublabel).display:inlineinlinenonenonenonenonenoneB. jsdom render of
GanttViewat container width 800, reading the two Start/End cells of a data row:and the list header at that width renders only
Task Nameplus the open-details spacer — theStartandEndheader captions are gone too.A and B are the same width, so at 800px both gates are shut simultaneously: no columns, no sublabel.
The band is wider than the default case
Gate 1 keys off the task-list width, not the viewport, and the user can drag the splitter down to
TASK_LIST_MIN_W= 160. So the hole also opens at 1024px and above whenever the persisted layout holds a dragged width under 280 — and a dragged width is the only waytaskListWidthis ever anything but the three defaults, since there is no prop and noGanttConfigSchemakey for it.There is a mirror-image hole at the other end: a viewport under 640px with the task list dragged wider than 280 satisfies
showStartEndColumns, but the columns also carry Tailwind'shidden sm:block, so the viewport keeps them hidden whilegantt-sm-hiddenis inactive — that one lands the right way up (the sublabel shows).What is left when both gates shut
Only the bar hover tooltip, which is itself conditional: the tooltip prints
Aug 26 → Sep 2only whentask.fieldsis empty. Configure the documentedtooltipFieldskey and the tooltip renders those fields instead, at which point a row's start and end dates are not readable anywhere in the view without opening the detail drawer.Inline edit is caught by the same gate: the Start/End cells are also where the two
type="date"inputs live, so at a task-list width under 280 an inline-editing user can edit the title but cannot see or change the dates.Suggested directions — maintainer's call, none proposed as decided
tooltipFieldsdefeats it.Related: #7204 (the same two functions, at 1024px and wider). Fixing this one likely settles the shape question #7204 is currently blocked on, so they probably want to be decided together.
Generated by Claude Code