diff --git a/client/src/components/PDF/TripPDF.test.ts b/client/src/components/PDF/TripPDF.test.ts index e790275ec..4f79d4ea5 100644 --- a/client/src/components/PDF/TripPDF.test.ts +++ b/client/src/components/PDF/TripPDF.test.ts @@ -1014,4 +1014,20 @@ describe('page breaks between days (#1292)', () => { const rule = html.slice(html.indexOf('.day-accommodation {')) expect(rule.slice(0, rule.indexOf('}'))).toContain('break-inside: avoid') }) + + // Measured against Chromium: with the days flowing, a header bar could be left + // at the foot of a sheet while its content moved on, and the repeat from #1471 + // then read as the same day printed twice. break-after on the thead and + // break-before on the tbody are both ignored; holding the day together is what + // works, and a day too long for one page still breaks and still repeats. + it('FE-PDF-BREAK-008: a flowing day is held together so its header is never stranded', async () => { + localStorage.setItem('trek_pdf_page_break_per_day', '0') + await downloadTripPDF(twoDays) + const html = getIframe()!.srcdoc + + expect(html).toContain('.pdf-flow .day-section { break-inside: avoid; page-break-inside: avoid; }') + // Scoped: a day that starts its own page cannot strand a header. + const at = html.indexOf('.day-section { break-inside: avoid') + expect(html.slice(at - 10, at)).toContain('.pdf-flow ') + }) }) diff --git a/client/src/components/PDF/TripPDF.tsx b/client/src/components/PDF/TripPDF.tsx index 174b20dc5..1f2856651 100644 --- a/client/src/components/PDF/TripPDF.tsx +++ b/client/src/components/PDF/TripPDF.tsx @@ -542,6 +542,15 @@ export async function downloadTripPDF({ trip, days, places, assignments = {}, ca .day-break { page-break-before: always; } .pdf-flow .day-break { page-break-before: auto; } .pdf-flow .day-section + .day-section { margin-top: 18px; } + /* Hold a flowing day together. Without this the header bar can be placed at the + foot of a sheet while its content moves to the next one, which then repeats + the header (#1471) and reads as the same day printed twice. A day too long + for one page still breaks and still repeats its header — the engine only + honours this where it can. Days that start a page of their own cannot strand + a header, so it is scoped to the flowing layout. + Measured, not assumed: break-after on the thead and break-before on the tbody + are both ignored by Chromium here. */ + .pdf-flow .day-section { break-inside: avoid; page-break-inside: avoid; } .day-section { width: 100%; border-collapse: collapse; table-layout: fixed; } .day-header-bar { background: #0f172a; padding: 11px 28px;