Hold every calendar cell to the same size

A calendar whose boxes resize is not a calendar. Each week row is its own
grid, and a bare 1fr track takes its minimum from its content, so the one
week containing "Alla helgons dag" had its seven cells squeezed while
every other week's stayed wide. The tracks are now minmax(0, 1fr) and the
cell, the day and the holiday name each refuse to contribute an intrinsic
width; the name clips to an ellipsis and keeps its full text in the title.

Row height follows the same rule: the band lanes are reserved from the
month's tallest week rather than each row's own, so a week with no leave
in it stands as tall as the week beside it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ei7gCZzdd751uZtPzb1Pep
This commit is contained in:
2026-09-19 14:08:04 +02:00
parent 224fe7ae3e
commit f0f537c95f
6 changed files with 281 additions and 6 deletions
@@ -0,0 +1,52 @@
/**
* The calendar grid must never change cell size: every day cell in the
* displayed month is the same width, and every week row is the same
* height, regardless of what any single cell contains.
*
* October 2026 is the exact month from the reported bug: its last week row
* (v.44) contains 31 October, "Alla helgons dag" — that long holiday name
* used to inflate only THAT row's grid track minimums (each week is its own
* separate CSS Grid — see `calendar.css`'s `.calendar-week` comment), so its
* seven day cells rendered narrower and misaligned against every other row.
* The fix (`minmax(0, 1fr)` tracks + `min-width: 0` on the cell/holiday-name
* elements, plus lifting `--band-reserved-height` to the month's max lane
* count) is unit-tested in `styles`/`CalendarWeek.test.tsx`/`Calendar.test.tsx`,
* which can't assert real layout (jsdom does none) — this spec is the one
* check that a real browser actually renders it uniformly.
*/
import { test, expect } from '@playwright/test'
import { goToCalendarMonth } from '../support/calendarNav'
test('every day cell in October 2026 is the same width, and every week row the same height', async ({ page }) => {
await goToCalendarMonth(page, new Date('2026-10-15T00:00:00Z'))
// Confirm the long-name row is actually present — otherwise this test
// would pass for the wrong reason (no distorting content at all).
await expect(
page.getByTestId('calendar-day-holiday-name').filter({ hasText: 'Alla helgons dag' }),
).toBeVisible()
const dayCells = page.locator('[data-testid="calendar-day"]')
const dayCount = await dayCells.count()
expect(dayCount).toBeGreaterThan(28) // at least 5 full week rows
const widths: number[] = []
for (let i = 0; i < dayCount; i++) {
const box = await dayCells.nth(i).boundingBox()
if (!box) throw new Error(`calendar day cell ${i} has no bounding box — is it actually visible?`)
widths.push(box.width)
}
expect(Math.max(...widths) - Math.min(...widths)).toBeLessThanOrEqual(1)
const weekRows = page.locator('.calendar-week')
const rowCount = await weekRows.count()
expect(rowCount).toBeGreaterThan(3) // October 2026 spans 5-6 Mon-Sun rows
const heights: number[] = []
for (let i = 0; i < rowCount; i++) {
const box = await weekRows.nth(i).boundingBox()
if (!box) throw new Error(`week row ${i} has no bounding box — is it actually visible?`)
heights.push(box.height)
}
expect(Math.max(...heights) - Math.min(...heights)).toBeLessThanOrEqual(1)
})