feat(templates): add the NorthlineProposal structured proposal preset - #610
Merged
DemchaAV merged 1 commit intoAug 30, 2026
Merged
Conversation
Comment on lines
+157
to
+158
| row.verticalAlign(RowVerticalAlign.TOP) | ||
| .gap(SUMMARY_GAP) |
| double separatorHeight = GOAL_TEXT_LINES * (TABLE_SIZE * LATO_LINE + BODY_LEADING); | ||
| page.addRow("GoalCells", row -> { | ||
| row.margin(DocumentInsets.top(BAND_TOP)); | ||
| row.verticalAlign(RowVerticalAlign.TOP).gap(GOAL_GAP); |
Comment on lines
+320
to
+321
| row.verticalAlign(RowVerticalAlign.TOP) | ||
| .gap(SCOPE_GAP) |
Comment on lines
+94
to
+95
| row.verticalAlign(RowVerticalAlign.TOP) | ||
| .gap(0) |
Comment on lines
+198
to
+199
| row.verticalAlign(RowVerticalAlign.TOP) | ||
| .gap(MONEY_GAP) |
Comment on lines
+312
to
+313
| row.verticalAlign(RowVerticalAlign.BOTTOM) | ||
| .gap(6) |
Comment on lines
+67
to
+68
| row.verticalAlign(RowVerticalAlign.CENTER) | ||
| .gap(LOGO_SIZE * 0.25) |
DemchaAV
changed the base branch from
feat/proposal-structured-data
to
feature/template-promotion
August 30, 2026 17:57
The proposal family had one preset on the narrative model. Northline Proposal is the first preset on the structured model: a two-page teal-and-navy business proposal on the Spectral/Lato pair - brand header with logo mark and wordmark, three title lines stacked on the reference's own pitch, the executive summary beside an at-a-glance fact card, icon goal cells, a numbered scope list, deliverable columns, the four-column phase grid, an investment table with subtotal / optional / total row styling, and a signing card. The navy footer band, the teal page-number block and the 01/02 page numbers are page chrome (PageBackgroundFill + DocumentHeaderFooter), not flow content, so the preset owns its session geometry. The icon set ships inside the templates artifact and resolves by the tokens the data carries; a blank token degrades gracefully and an unknown one is reported as a data error by name, as is a phase-grid header count that does not match the four rendered columns. qa: one fixtures class feeds the smoke, the exact two-page layout snapshot, and the pixel gate; the smoke drives full layout and render (empty document included) and asserts the table text on the rendered text layer, where the snapshot cannot see. Examples gain NorthlineProposalV2Example (proposal-northline-v2 in the showcase) with its committed preview.
DemchaAV
force-pushed
the
feat/proposal-northline-preset
branch
from
August 30, 2026 19:07
686a95e to
c176f66
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The proposal family renders one look —
ModernProposalon the narrative model. The structured proposal model landed in #609 with no consumer; this PR adds the first one: the two-page teal-and-navy "Northline" business proposal look, previously available only as a standalone published template pinned tograph-compose:2.2.0, with its icons on the filesystem and its own spec.What changed
proposal/presets/NorthlineProposal—DocumentTemplate<StructuredProposalDocumentSpec>viacreate(). Page one: brand header (logo mark, wordmark, tracked document label viaTextOrnaments.spacedUpper), three title lines stacked at the reference's own pitch (tighter than the font's line height, unreachable through additive leading — so the pitch is an anchor, not text layout), the meta line, the executive summary beside the glance fact card, flattened icon goal cells (the engine refuses a row inside a row cell), and the numbered scope list. Page two: deliverable bullet columns, the four-column phase grid (the one region with vertical rules and therefore the one real table), the investment / terms band, and the signing card.PageBackgroundFills, the brand line and0{page}numbers a FOOTER-zoneDocumentHeaderFooter, and the bottom page margin equals the band height — so the preset owns its session geometry (size, margins, page background), documented onRECOMMENDED_MARGIN. Like the ported template it issues no explicit page break (a break after the natural advance leaves a blank page); the two-page distribution is a property of reference-volume content and the class Javadoc says so.NorthlineStyles(measured geometry + Spectral/Lato text roles; preset-local — the look has no second consumer yet, the orange variant parameterises the colours when it lands),NorthlineWidgets(header, icon-badged section heading, teal bullet),NorthlinePageOne/NorthlinePageTwo(the bands), andNorthlineIcons(classpath loader with a per-token cache).templates/proposal/northline/icons/; icon tokens are data, so a blank token degrades gracefully (plain badge disc / column-preserving spacer) and an unknown one throwsIllegalArgumentExceptionnaming the token — the same class the phase-grid header contract throws whencolumnHeadersdoes not carry one label per rendered column.NorthlineProposalFixtures(the reference content, kept in lockstep with the examples module's sample data by cross-reference) feeds all three gates —NorthlineProposalSmokeTest(7 tests: identity, canonical render throughtoPdfBytesproving the packaged icons resolve, the empty document through the section guards, rendered-text assertions on the phase grid and investment table — both are single leaf nodes in the layout snapshot, the recorded composed-cell blind spot — and the three data-error contracts),NorthlineProposalLayoutSnapshotTest(exact two-page geometry, page count asserted),NorthlineProposalVisualParityTest(both pages vs checked-in baselines, standard budget).NorthlineProposalV2Example+StructuredProposalSampleData, registered inGenerateAllExamplesand the showcase metadata; theproposal-northline-v2preview is committed beside the other previews (web/examples.jsonpicks the row up at its release-time regeneration). CHANGELOG entry underv2.2.3 — Planned / Templates.Verification
Full reactor gate (the eight CI modules) → BUILD SUCCESS; proposal qa suite 18/18 green (
-f qa/pom.xml); examples suite 75/75 green includingCommittedAssetDriftTestwith the new preview;javadoc:javadocclean.Port parity, verified on one machine against the published template itself: the preset rendered with the template's own example data is pixel-identical to the standalone template's render on the current engine — 0 / 2,173,720 differing pixels on each of the two pages — and the resolved layout snapshots are node-identical (175/175 paths, zero geometry deltas > 0.01pt). Against the template's approved 2.2.0 preview the only delta is the released ligature fix (#601, v2.2.1): geometry is identical and the differing pixels are exactly the letter-drawn
tipairs.Notes
Lane: canonical (templates.proposal + qa + examples) — no engine changes. Stacks on #609; merge that first.