Clamp an expanded bar to the board, and count it in the start markers
Two related ways an occurrence that only arrived through Timeline's expand prop could disagree with the board it was drawn onto: - `right` was computed but never clamped to chartWidth, while `left` was clamped to 0. boardWindow's max is derived from `plotted` alone, so a base row can never exceed it — but occurrencesOf admits any occurrence starting at or before the window's edge, and one with no stated end then runs a full interval past it. Inside overflow-auto that grows the pane's scrollWidth, so the reader scrolls into empty space with no gridlines or axis. The spec says a rule may fill the board but must never enlarge it; `right` is now clamped the same way `left` already was. - startMarkers read from `plotted` rather than `drawn`, so a "3 events start <day>" label under-counted whatever expand had added to that day. Pointed at `drawn`. The existing "boardWindow is not widened by expansion" test only pinned boardWindow's own purity and never rendered Timeline, despite its comment claiming the ordering was "asserted structurally in the component below" — no such assertion existed, and moving the expand call above boardWindow left the suite green. Added a render-level regression test that compares the rendered chart width with and without an expand returning far-future occurrences; confirmed it fails if expand is called before boardWindow. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b0523a7cb9
commit
d1ffac4b9f
@@ -253,7 +253,10 @@ export function Timeline({
|
||||
}
|
||||
|
||||
const lanes = timelineLanes(drawn, group, splitUpcoming, gameOrder);
|
||||
const marks = startMarkers(plotted, x);
|
||||
// From `drawn`, not `plotted`: the bars on the board include whatever
|
||||
// `expand` added, and a start-marker label counting only the base rows
|
||||
// under-counts what is actually drawn there.
|
||||
const marks = startMarkers(drawn, x);
|
||||
|
||||
const months = monthBoundaries(min, max);
|
||||
const weeks = weekBoundaries(min, max);
|
||||
@@ -433,7 +436,28 @@ export function Timeline({
|
||||
// reserved for genuinely truncated ones.
|
||||
const clippedStart = clock.startsMs < min;
|
||||
const left = Math.max(x(clock.startsMs), 0);
|
||||
const right = x(clock.endsMs ?? clock.startsMs + 14 * DAY);
|
||||
// `boardWindow`'s `max` is derived from `plotted` alone, so a
|
||||
// base row can never run past it — but an expanded occurrence
|
||||
// can: `occurrencesOf` admits anything *starting* at or before
|
||||
// the window's edge, and one with no stated end then runs a
|
||||
// full interval past it. Clamped the same way `left` is
|
||||
// clamped to 0, so a rule can fill the board but never enlarge
|
||||
// it — growing `overflow-auto`'s scrollWidth into empty space
|
||||
// with no gridlines or axis is exactly what the board exists
|
||||
// to avoid.
|
||||
// `boardWindow`'s `max` is derived from `plotted` alone, so a
|
||||
// base row can never run past it — but an expanded occurrence
|
||||
// can: `occurrencesOf` admits anything *starting* at or before
|
||||
// the window's edge, and one with no stated end then runs a
|
||||
// full interval past it. Clamped the same way `left` is
|
||||
// clamped to 0, so a rule can fill the board but never enlarge
|
||||
// it — growing `overflow-auto`'s scrollWidth into empty space
|
||||
// with no gridlines or axis is exactly what the board exists
|
||||
// to avoid.
|
||||
const right = Math.min(
|
||||
x(clock.endsMs ?? clock.startsMs + 14 * DAY),
|
||||
chartWidth,
|
||||
);
|
||||
const width = Math.max(right - left, MIN_BAR);
|
||||
const done = isDone(event.id);
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user