feat(cv-v2): migrate Panel preset#62
Merged
Merged
Conversation
Ports the legacy Panel CV preset (PanelCvTemplateComposer stacked layout) onto the v2 layered architecture. The preset reads as four equal-width panels of the same shell: * Header card — pale-teal fill, centred Poppins UPPERCASE name, optional job title, centred meta + link line. Name paragraph is inlined instead of going through Headline.uppercaseCentered because that widget rewrites the card's padding via host.padding(...) which otherwise leaks into a visibly wider header outline. * Profile card — full-width white card with UPPERCASE teal title, bronze-like teal accent strip, and the summary paragraph. * Two-column row — left card stacks Skills + Education + Additional, right card stacks Experience + Projects. Each card is its own panel with the shared shell. * All cards (header, profile, side modules) share a single CardWidget.Style: stroke 0.45pt, padding(bannerInnerPadding=8), cornerRadius(7). Only fillColor differs (header tinted teal vs panels white). Section widths are anchored explicitly. v2 engine sections default to fit-content widths inside a vertical column, so a card with long content (Skills) would otherwise render visibly wider than a card with short content (Education). The new widthAnchor(card, width) helper drops a zero-height spacer of the pre-computed target width as the card's first element, pinning every panel to identical outer widths regardless of paragraph length. Body rendering uses a preset-local dispatcher because the engine bans nested horizontal rows and the side cards sit inside flow.addRow. EntriesSection headers therefore use EntryCompactRenderer.titleDateBody (single 'title - date' paragraph) instead of the standard EntryRenderer's 2-column Row header. Theme additions are additive: * CvPalette.panel() — body slate ink, pale teal stroke + banner fill. * CvTypography.panel() — Poppins/Lato 22/8.9/10.4/9.4/9.4/9.0/9.4 1.2. * CvSpacing.panel() — 6pt page-flow gap, 8pt card padding, 2.2pt accent strip, 7pt corner radius. * CvTheme.panel() factory wires the three above with the classic decoration. CardWidget gains a PageFlowBuilder overload so top-level cards (Profile) can be rendered directly under PageFlowBuilder without an intermediate wrapper section. The applyStyle path is shared between both render() overloads. Tests: * CvV2VisualParityTest now exercises 11 presets (added Panel); 11/11 pass at the existing 50k pixel-diff budget against the new visual-baselines/cv-v2-layered/panel-page-0.png baseline (single page). * PanelSmokeTest covers stable identity + default-factory and custom-theme render paths.
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.
Summary
Ports the legacy Panel CV preset (
PanelCvTemplateComposerstacked layout) onto the v2 layered architecture. The page reads as four equal-width panels sharing one card shell.Visual layout
Architectural decisions
widthAnchor(card, width)drops a zero-height spacer of the pre-computed target width as the card's first element, pinning every panel to identical outer widths.Headline.uppercaseCenteredrewrites the host card's padding viahost.padding(theme.spacing().headlinePadding()), which would override the CardWidget padding and leak a wider outline for the header vs every panel below it. Inlined paragraph preserves the shared shell.flow.addRow.EntriesSectionheaders therefore useEntryCompactRenderer.titleDateBody(single 'title - date' paragraph) instead of the standardEntryRenderer2-column Row header.CardWidgetoverload — addedrender(PageFlowBuilder, ...)so full-width top-level cards (Profile) render directly under PageFlowBuilder without an intermediate wrapper. The applyStyle path is shared between both render() overloads.Theme additions — additive
CvPalette.panel()— body slate ink, pale teal stroke + banner fill.CvTypography.panel()— Poppins/Lato, 22/8.9/10.4/9.4/9.4/9.0/9.4, 1.2 line spacing.CvSpacing.panel()— 6pt page-flow gap, 8pt card padding, 2.2pt accent strip, 7pt corner radius.CvTheme.panel()factory wires the three above with the classic decoration.Test plan
./mvnw test -Dtest=com.demcha.compose.document.templates.cv.v2.presets.PanelSmokeTest -pl .— 3/3./mvnw test -Dtest=com.demcha.compose.document.templates.cv.v2.presets.CvV2VisualParityTest -Dgraphcompose.visual.approve=true -pl .— 11/11 first-time baseline approval./mvnw test -Dtest=com.demcha.compose.document.templates.cv.v2.presets.CvV2VisualParityTest -pl .— 11/11 without approve (baseline locked in)examples/target/generated-pdfs/templates/cv/cv-panel-v2.pdf— all 6 panels render at identical column widthsFiles
CvPalette.java,CvTypography.java,CvSpacing.java,CvTheme.java,CardWidget.java,CvV2VisualParityTest.javapresets/Panel.java,presets/PanelSmokeTest.java,cv-v2-layered/panel-page-0.pngbaseline,examples/.../CvPanelExample.java