feat(DTCRCMERC-4687): implement v5 text-layout styles for renderV2Message#1331
feat(DTCRCMERC-4687): implement v5 text-layout styles for renderV2Message#1331sailaya99 wants to merge 3 commits into
Conversation
…sage - Add body reset and scoped .pp-message stylesheet (display:block, width:100%) - Map text.color to CSS classes on .main/.action spans with vertical-align:middle - Add CSS filters on .logo img for white (invert), monochrome (grayscale+black), grayscale variants - Handle logo positions: left (default), right (margin swap), top (block display) - Implement fontSource @font-face generation with URL/name security validation - Wire fontSource through message.jsx into styles() - Add data-pp-style-* root attributes for layout, logo-type, logo-position, text-align, text-color, text-size - Add greyscale alias pipeline test (validateStyle -> render -> class) - Expand snapshot coverage to all 7 text sizes (10-16) and full logo/color/align matrix (21 snapshots)
Braluna-pp
left a comment
There was a problem hiding this comment.
Thermo-nuclear code quality review: a few maintainability and coverage issues worth tightening before this lands.
- Separate logoType/logoPosition in message.jsx; buildLogoConfiguration now branches on logoType=inline without using it as a pseudo-position - Replace full-matrix snapshots with one representative render snapshot, one stylesheet snapshot, and test.each matrix assertions (119 lines vs ~1240) - Add stylesheet isolation tests (inline embed + selector scope check) - Simplify redundant selector-parsing filter in isolation test
Braluna-pp
left a comment
There was a problem hiding this comment.
Thermo-nuclear code-quality review: leaving three maintainability findings inline.
Braluna-pp
left a comment
There was a problem hiding this comment.
LGTM thank you for addressing the feedback
There was a problem hiding this comment.
I’m concerned that renderV2Message currently renders logo image blocks directly from item.source_url. That does not match legacy PMC behavior or the v6 renderer closely enough for first-party logos.
Legacy PMC does use <img>, but the src comes from local PayPal logo assets generated through @paypal/sdk-logos and selected by style mutations like logo.type and text.color. v6 similarly does not render arbitrary image URLs for brand logos; it maps image content blocks into known local SVG templates via brandTemplate/graphicTemplate.
For PayPal and PP Credit logos, I think we should resolve the logo locally from the semantic image block plus logo.type, logo.position, and text color. That keeps rendering deterministic, makes logo.type actually control the displayed logo variant, and avoids depending on CPS-provided asset URLs for core brand presentation.
A reasonable implementation path for this PR would be to reuse or adapt the existing legacy PMC logo resolver/data-URI assets rather than porting the full v6 inline SVG implementation. If source_url still needs to be supported, I’d treat it as fallback-only and document/validate or allowlist it explicitly.
There was a problem hiding this comment.
I agree with Jeremy’s concern here. The current implementation makes the v2 IMAGE block URL the source of truth for first-party branding:
case 'IMAGE':
return <img src={item.source_url} alt={item.alternative_text || 'PayPal'} />;That means logo.type, logo.position, and text.color mostly affect wrapper classes/CSS, but they do not actually choose the logo asset. For example, logo.type: primary and logo.type: alternative can still render the same CPS-provided source_url.
Legacy PMC handles this differently. The logo asset is renderer-owned, and the style options select the variant:
['text.color:white && logo.type:primary', { logo: Logo.PP_PAYPAL.WHITE }],
['text.color:grayscale && logo.type:primary', { logo: Logo.PP_PAYPAL.GRAYSCALE }],
['text.color:monochrome && logo.type:primary', { logo: Logo.PP_PAYPAL.MONOCHROME }],
['text.color:white && logo.type:alternative', { logo: Logo.PP_PAYPAL.WHITE[0] }],Then the renderer uses the resolved local/logo object:
{logos.map(({ src, dimensions: [width, height] }) => (
<div className="message__logo message__logo--svg">
<img src={src} alt="" role="presentation" />
<canvas height={height} width={width} />
</div>
))}I think the right path is to keep this PR’s simple v2 renderer shape, but add a small first-party logo resolver before rendering the image. Something like:
resolveLogoBlock({
block: logoBlock,
logoType,
logoPosition,
textColor
});For known first-party blocks like paypal_logo and PayPal Credit logo names, that resolver should pick from the existing PMC logo assets based on logo.type and text.color. For unknown/non-first-party image blocks, source_url can remain the fallback path.
So the behavior would be:
if (isKnownPayPalLogo(block.name)) {
return getLocalPayPalLogo({ logoType, textColor });
}
if (isKnownPayPalCreditLogo(block.name)) {
return getLocalPayPalCreditLogo({ logoType, logoPosition, textColor });
}
return { src: block.source_url };That keeps the implementation small, avoids bringing back the full v5 mutation system, but still makes the core PayPal brand rendering deterministic and style-driven.
I’d also add tests for:
- known
paypal_logodoes not render the CPSsource_url logo.type: primaryvsalternativeresolves different local assetstext.color: white/monochrome/grayscaleresolves the matching local variant- unknown image blocks still fall back to
source_url
Description
Implements v5 text-layout styles for the renderV2Message SSR module (DTCRCMERC-4687).
Previously, renderV2Message rendered with a bare .pp-message container and minimal CSS — no color treatment, no logo positioning styles, no font configuration, and no alignment support. This PR introduces a static, class-based stylesheet (no legacy mutation system) that covers all v5 text style options:
Root data-pp-style-* attributes are added to the .pp-message div for downstream observability and potential CSS hook use.