Fix multi-column Row NaN (default cells to column count) + border wid…#35
Merged
Merged
Conversation
…th px unit Two type-checks-but-renders-broken footguns found by cold-start agent testing: - A multi-column <Row> with no `layout`/`cells` defaulted `cells` to `[1]` regardless of column count, so the 2nd/3rd <Column> had no cell and rendered width="NaN". Default to one equal cell PER <Column> child, matching renderToJson. (Also makes a `layout` accidentally placed on <Column> harmless — the Row no longer NaNs.) - A number border width (`borderTopWidth: 1`) rendered `border-top: 1 solid` (invalid CSS the browser drops), even though BorderInput + its JSDoc accept a number. Normalize border *Width fields (number / unit-less numeric string → px) in the mapper, for both nested `border` objects and gathered flat side props. +6 tests (shared mapper normalization + react render-level for both). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes two render-time “type-checks-but-breaks” cases in the React email renderer by (1) defaulting <Row> cell layouts to match the number of <Column> children (preventing NaN widths) and (2) normalizing border width values so unitless widths render as valid CSS (Npx).
Changes:
- Default
<Row>cellsto one equal cell per direct<Column>child when neitherlayoutnorcellsis provided. - Normalize
border*Widthvalues (number / unitless numeric string →"Npx") inside the semantic-props mapper, including gathered flat side props. - Add regression tests covering both behaviors at the shared mapper level and at the React render-to-HTML/JSON level.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/shared/src/utils/semantic-props.ts | Adds border width normalization in mapSemanticProps after border-side prop gathering. |
| packages/shared/src/utils/semantic-props.test.ts | Adds unit normalization tests for nested and gathered border width props. |
| packages/react/src/dx-footguns.test.tsx | Adds regression tests ensuring no NaN widths for multi-column Rows and px units for border widths. |
| packages/react/src/components/Row.tsx | Updates default cells behavior to match <Column> child count when layout/cells are omitted. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The width normalization mutated final.border in place, but final.border can alias the caller's object (the values escape hatch is a shallow clone; a nested border prop passes by reference) — so a reused const HAIRLINE would be rewritten to '1px' as a side effect. Clone before rewriting, reassign. +purity test. 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.
…th px unit
Two type-checks-but-renders-broken footguns found by cold-start agent testing:
A multi-column with no
layout/cellsdefaultedcellsto[1]regardless of column count, so the 2nd/3rd had no cell and rendered width="NaN". Default to one equal cell PER child, matching renderToJson. (Also makes alayoutaccidentally placed on harmless — the Row no longer NaNs.)A number border width (
borderTopWidth: 1) renderedborder-top: 1 solid(invalid CSS the browser drops), even though BorderInput + its JSDoc accept a number. Normalize border *Width fields (number / unit-less numeric string → px) in the mapper, for both nestedborderobjects and gathered flat side props.+6 tests (shared mapper normalization + react render-level for both).
Summary
What does this PR do? Keep it brief.
Changes
Test Plan
pnpm buildpassespnpm testpassesNotes
Any additional context for reviewers.
📖 Storybook Preview: https://unlayer.github.io/elements/pr/35/