Render parity: content-width image sizing, containerPadding, unique IDs#32
Merged
Merged
Conversation
Item exporters received no column/body context, so the width-aware image exporter fell back to a fixed ~500px regardless of contentWidth or column count — full-width images rendered small and images in multi-column rows could overflow their column. Column now threads its index, the row cells, and the row/column/body values to its item children, and renderComponent surfaces them on the exporter `meta`, so the exporter computes the available width (contentWidth × column fraction, minus padding) the same way the editor does. A standalone item (no Body) now defaults contentWidth to 500 to match the schema default. Result: a full-width image fills the content width, an image in a 3-column row sizes to ~1/3, and nothing overflows. Updates the golden snapshot to the corrected sizes; adds regression tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… px) containerPadding (an item's content-wrapper padding) was threaded at runtime but only typed as a string and never exposed on item props — so containerPadding="10px" was a type error, and a bare number would render unitless. Type it as SizeInput on the item base props and normalize a number to px in Column, matching the other size props. Renders identically to the equivalent px string. Adds render + type tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + editor) renderToHtml generated ids per element position, so multi-row designs repeated u_row_1 / u_column_1 / u_content_*_1 — invalid HTML5 and out of step with both renderToJson (a global counter) and the editor (unique stored ids). Thread a per-render id counter on _config (reset by Body, shared by reference down the tree, SSR-safe) so every body/row/column/content id is unique. Updates the multi-element snapshots (id attributes only); adds a uniqueness test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR closes several render-parity gaps between renderToHtml output and the Unlayer editor by threading full body/row/column context into item exporters (notably for width-aware image sizing), normalizing containerPadding as a typed item prop, and making generated HTML element IDs unique across an entire render.
Changes:
- Thread row/column/body context into item exporters via
metato compute available widths correctly (fixing image sizing vs. real content width and column fractions). - Add
containerPaddingto base item props (SizeInput) and normalize numeric values topxinColumn. - Introduce per-render ID counters on
_configand use them forBody,Row,Column, and content wrapper IDs to avoid duplicates.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/react/src/utils/render-to-html.test.tsx | Adds regression test asserting no duplicate u_* IDs across a multi-row tree. |
| packages/react/src/utils/create-component.tsx | Adds containerPadding to item base props, threads metaContext to exporters, and introduces nextHtmlId plus standalone body width default. |
| packages/react/src/dx-types.test-d.tsx | Type-gate coverage for containerPadding accepting number and string values. |
| packages/react/src/dx-behaviors.test.tsx | Behavioral tests for containerPadding number→px normalization and string pass-through. |
| packages/react/src/components/Row.tsx | Switches row htmlID generation to nextHtmlId (global per-render uniqueness). |
| packages/react/src/components/Image.test.tsx | Regression tests for contentWidth-aware image sizing in 1-col and 3-col layouts. |
| packages/react/src/components/Column.tsx | Threads column/body context to items, normalizes numeric containerPadding, and uses nextHtmlId for column/content IDs. |
| packages/react/src/components/Body.tsx | Resets per-render ID counters on _config and uses nextHtmlId for body ID. |
| packages/react/src/components/snapshots/snapshots.test.tsx.snap | Snapshot updates for changed content wrapper IDs. |
| packages/react/src/snapshots/golden-template.test.tsx.snap | Snapshot updates reflecting unique IDs and corrected image width/max-width sizing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ped "500px" Use the CSS-string "500px" (matching BodyDefaults.contentWidth) for the standalone-item contentWidth default instead of a bare number, so the value is a CSS string everywhere it might be consumed. Behavior-neutral — the image exporter parseFloats it either way; addresses a review note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Fixes the rendering-engine gaps surfaced by testing cold-start agents on 0.1.12. Each change is verified to match what the editor does.
Fixes
1. Images size against the real content width (no more 500px cap)
Item exporters got no column/body context, so the width-aware image exporter fell back to ~500px regardless of
contentWidthor column count — full-width images rendered small and images in multi-column rows could overflow.Columnnow threads its index, row cells, and row/column/body values to its items, andrenderComponentsurfaces them on the exportermeta, so the exporter computes the available width (contentWidth × column fraction, minus padding) exactly as the editor does (the computation already lives in@unlayer/exporters). A standalone item defaultscontentWidthto 500 to match the schema default.Result: full-width image fills the content width, a 3-column image sizes to ~1/3, nothing overflows.
2.
containerPaddingis a typed item prop (number → px)It was threaded at runtime but only typed as a string and never exposed on item props — so
containerPadding="10px"was a type error and a bare number rendered unitless. Now typed asSizeInputon the item base props, with number→px normalization inColumn. Renders identically to the px string.3. Unique element IDs in
renderToHtmlrenderToHtmlreset ids per element position, so multi-row designs repeatedu_row_1/u_column_1/u_content_*_1— invalid HTML5 and out of step with bothrenderToJson(a global counter) and the editor (unique ids). A per-render id counter on_config(reset by Body, shared by reference, SSR-safe) now makes every id unique. Snapshot updates are id-attributes only.Already at editor parity (verified, no change)
Page.backgroundColorin web mode — the editor's web body exporter doesn't put it on the wrapper either (onlyemail()does); web pages set it on the host document<body>. Confirmed against@unlayer/exporters@1.415.0.Headingtext entity handling — matches the editor'sunescape(text).border*onColumn— already type-checks and renders.Tests & CI
containerPaddingrender + type (dx-behaviors + dx-types gate), unique-id guard (render-to-html.test.tsx).pnpm test, the type gate via the "Type contract" step.build✅ ·typecheck✅ · 339 tests ✅. Verified against a packed build and against the editor's own exporter output.Backward-compatible (image sizes are now correct, not different by intent) — ships as a patch.
📖 Storybook Preview: https://unlayer.github.io/elements/pr/32/