One month-range picker, and a single month that is not a dead chart

Rendered evidence for PR #6688 — items 4.8 (the dashboard chart goes dead on a single month) and 3.3 (the leasing tab has no date filter).

2026-08-31 · captured from a dev server on branch gera/sean-4-8-range-picker, local data · read-only, nothing written

4.8 — the dead chart, and what killed it

One line of chart code. ObservabilityChart drew a line from a coordinate list and skipped any series with fewer than two points. The dashboard inspector is months-only, so a one-month window buckets to exactly one point — and the chart rendered nothing.

It was not even the empty state. TrendView's “No data for this range” keys on length === 0, and one is not zero, so the reader got gridlines, an axis label, and silence over a real reading.

Below: Occupancy, expanded, with June 2026 picked in the month grid. Same page, same data, same click path — the halves differ by this diff and nothing else (the AFTER shot is the branch; the BEFORE shot is the branch with ObservabilityChart.tsx reverted to origin/main, so the resolver is held constant and only the chart layer moves).

Before — 85.8% is on the card, nowhere on the plot

Occupancy chart with a single month selected: gridlines, a Jun label, and no plotted mark

After — the reading is drawn, centred under its own label

The same chart with the single reading rendered as a mark at 85.8%

Measured in the same run: [data-chart-single-point] count 0 before, 1 after; four stroked paths in both (the gridlines and the brush rail), which is why the plot looked plausible rather than broken.

The mark is the floor, not the whole fix

Occupancy is served from the monthly store — one reading per month — so no finer grain can split a single month, and the mark is the whole truth about that window. Where the data does have interior resolution, resolvePlotGranularity re-buckets one grain finer and the chart draws a real line:

WindowUnderlying seriesRequestedPlotted atPoints
One monthdaily readingsmonthweek6
One weekdaily readingsmonthday7
One monthmonthly readingsmonthmonth1 → mark
Four monthsdaily readingsmonthmonth4 → unchanged

It takes the coarsest grain that draws — weeks, never straight to days — so a months-only surface never quietly starts reading day-over-day. It only ever re-keys points already in the slice; nothing is invented, and a window that genuinely holds one reading resolves back unchanged. Pinned in single-month-not-dead.test.ts, whose cases carry their own positive control (each asserts the requested grain still produces the undrawable single bucket).

3.3 — the leasing tab now has the filter, and it is the same control

One component, one ladder, one persisted value. #6647 taught /leasing to READ a window. The only way to CHANGE it was to expand the card — so a reader looking at the collapsed pipeline had numbers over a window and no control for it.

The leasing page with a Trailing 3 months pill in the header
The pill prints the active window, not the word “Window”. Nothing is expanded — the control is on the collapsed page.
The window popover open, showing the shared months-only ladder
The shared ladder, derived from PERIOD_ORDER with PERIOD_MENU_LABEL's copy — the same rows the chart toolbar offers. No “Specific months…” grid here, deliberately: see below.
The leasing page after picking Trailing 12 months, showing 535 prospects
Picking Trailing 12 months. Prospects (3 mo) 380 → Prospects (12 mo) 535 — the number and its caption move together, off the same persisted card-window override the dashboard card reads.

Why this surface offers no specific-month grid

Not a taste call. These counts are recounted server-side through /api/leasing/stats?period=, whose vocabulary is PeriodKey — and presetToToken('custom') is null for the same reason. A committed span has nothing to be sent as, so the grid would open, take two clicks and an Apply, and change nothing.

The same rule closed two more of these on the dashboard, found while writing the test rather than in review:

Registered in the arsenal

The component library page showing the MonthRangePicker entry with a live preview
/admin/dev/components — reusable by construction, so it is in the registry with a Preview and a three-shape Variants gallery.

What was reused rather than forked

Honest limits of this page

Local dev data, not production — the numbers are this machine's, and the point is the control and the plot, not the counts. The before/after halves were captured in the same session against the same data with only ObservabilityChart.tsx swapped. The allowSpecificMonths gate on the leasing pill is shown as an absence, which is the honest way to show it: the assertion that it stays absent lives in leasing-hub-date-filter.test.tsx, along with a case that walks the whole ladder to prove no row is a dead one.

PropFlow Docs