Found in a browser pass over a real application's gantt view (objectstack-ai/duly#62). Filed unassigned, not claiming.
Measured on @objectstack/console 17.2.0 (objectui 190fbd01d061) in Chromium 1194 at 1440x900. Re-checked against current main84ffdbcbb33762b5488742fb902faf45a3742e93: the expression below is unchanged there, so this is not a version-lag report.
Symptom
The toolbar reads January 2026 while the timeline underneath it shows 26 Aug through 6 Sep 2026, Today marker on 1 September.

Cause
packages/plugin-gantt/src/GanttView.tsx — the toolbar span formats the range start:
<spanclassName="font-semibold text-xs sm:text-sm">{timelineRange.start.toLocaleDateString(dateLocale,{month: 'long',year: 'numeric'})}</span>timelineRange is the memo that spans the whole dataset. With no startDate prop it resolves to min(task.start) minus 7 days, snapped to the period; the end is max(task.end) plus 14 days. So the label names the first month of the entire dataset, and it cannot change while the chart is scrolled because it is not derived from scroll position at all.
The app in the screenshot holds tasks from 31 Jan to 31 Dec 2026, so this label sits on "January 2026" for every scroll position of an eleven-month timeline. On a first read it looks like the chart is showing January and the columns are mislabelled — the truth is the other way round.
The renderer already computes the right answer one row lower
Read from the DOM in the same frame as the screenshot:
| element | value |
|---|
| toolbar period label | January 2026 |
band header, data-testid="gantt-header-groups" | Aug 2026, Sep 2026 |
unit columns, data-testid="gantt-header-units" | 26W27T28F29S30S31M1T2W3T4F5S6S |
The band header is already a viewport-derived month label and it contradicts the toolbar directly above it. Whatever the toolbar is meant to say, two month labels four pixels apart disagreeing is the part a user sees.
Related, same toolbar: the two buttons beside the label are inert
The prevPeriod / nextPeriod buttons render an aria-label and an icon and carry no onClick:
<Buttonvariant="ghost"size="icon"className="h-8 w-8"aria-label={t('gantt.toolbar.prevPeriod')}><ChevronLeftclassName="h-4 w-4"/></Button>So the obvious recovery — "this says January, let me page forward to the month I am looking at" — does nothing, with no diagnostic. This is arguably the same defect: a period label and a pair of period-stepper buttons that are not wired to a period.
Reproduction
Any gantt whose dataset spans more than one month, scrolled anywhere other than its first month. The chart auto-scrolls to Today on load, so a dataset with history reproduces it on first paint with no interaction:
- A gantt view over rows whose start dates run from January to December of the current year.
- Load it. The chart lands on Today.
- Toolbar reads the January label; the columns and the band header read the current month.
Suggested direction — maintainer's call, not proposed as decided
Deriving the label from the visible window is the fix that makes the toolbar agree with the band header: the scroll offset already maps to a date (the pixel-to-date binary search used by the drag handlers), so the leftmost visible column's month is available without new state. The two stepper buttons then have something to drive — scroll by one unit of the current granularity.
The alternative reading is that the label is meant to describe the whole range, in which case it should say so (a start-to-end range, not a single month) and the stepper buttons should go. Either way the current pairing cannot be right.
Related: #7070 (gantt/timeline date-axis findings), #5132 (GanttViewMode doc line).
Found in a browser pass over a real application's gantt view (objectstack-ai/duly#62). Filed unassigned, not claiming.
Measured on
@objectstack/console17.2.0 (objectui190fbd01d061) in Chromium 1194 at 1440x900. Re-checked against currentmain84ffdbcbb33762b5488742fb902faf45a3742e93: the expression below is unchanged there, so this is not a version-lag report.Symptom
The toolbar reads January 2026 while the timeline underneath it shows 26 Aug through 6 Sep 2026, Today marker on 1 September.
Cause
packages/plugin-gantt/src/GanttView.tsx— the toolbar span formats the range start:timelineRangeis the memo that spans the whole dataset. With nostartDateprop it resolves tomin(task.start)minus 7 days, snapped to the period; the end ismax(task.end)plus 14 days. So the label names the first month of the entire dataset, and it cannot change while the chart is scrolled because it is not derived from scroll position at all.The app in the screenshot holds tasks from 31 Jan to 31 Dec 2026, so this label sits on "January 2026" for every scroll position of an eleven-month timeline. On a first read it looks like the chart is showing January and the columns are mislabelled — the truth is the other way round.
The renderer already computes the right answer one row lower
Read from the DOM in the same frame as the screenshot:
January 2026data-testid="gantt-header-groups"Aug 2026,Sep 2026data-testid="gantt-header-units"26W27T28F29S30S31M1T2W3T4F5S6SThe band header is already a viewport-derived month label and it contradicts the toolbar directly above it. Whatever the toolbar is meant to say, two month labels four pixels apart disagreeing is the part a user sees.
Related, same toolbar: the two buttons beside the label are inert
The
prevPeriod/nextPeriodbuttons render anaria-labeland an icon and carry noonClick:So the obvious recovery — "this says January, let me page forward to the month I am looking at" — does nothing, with no diagnostic. This is arguably the same defect: a period label and a pair of period-stepper buttons that are not wired to a period.
Reproduction
Any gantt whose dataset spans more than one month, scrolled anywhere other than its first month. The chart auto-scrolls to Today on load, so a dataset with history reproduces it on first paint with no interaction:
Suggested direction — maintainer's call, not proposed as decided
Deriving the label from the visible window is the fix that makes the toolbar agree with the band header: the scroll offset already maps to a date (the pixel-to-date binary search used by the drag handlers), so the leftmost visible column's month is available without new state. The two stepper buttons then have something to drive — scroll by one unit of the current granularity.
The alternative reading is that the label is meant to describe the whole range, in which case it should say so (a start-to-end range, not a single month) and the stepper buttons should go. Either way the current pairing cannot be right.
Related: #7070 (gantt/timeline date-axis findings), #5132 (
GanttViewModedoc line).