Skip to content

Commit c610dc0

Browse files
fix: padding in Container/Section failing on Klavyio and Outlook (#2257)
Co-authored-by: dielduarte <magdiel.kesller@gmail.com>
1 parent 556d790 commit c610dc0

7 files changed

Lines changed: 79 additions & 16 deletions

File tree

‎.changeset/forty-poets-wonder.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-email": patch
3+
---
4+
5+
fix: padding in Container/Section failing on Klavyio and Outlook desktop

‎packages/editor/src/extensions/__snapshots__/section.spec.tsx.snap‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ exports[`Section Node > renders React Email properly 1`] = `
1111
cellspacing="0"
1212
role="presentation"
1313
class="node-section"
14-
style="padding:10px 20px 10px 20px;box-sizing:border-box;text-align:center">
14+
style="box-sizing:border-box;text-align:center">
1515
<tbody>
1616
<tr>
17-
<td>Section content</td>
17+
<td style="padding:10px 20px 10px 20px">Section content</td>
1818
</tr>
1919
</tbody>
2020
</table>

‎packages/editor/src/extensions/container.spec.tsx‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,11 @@ describe('Container Node', () => {
293293
cellpadding="0"
294294
cellspacing="0"
295295
role="presentation"
296-
style="max-width:600px;align:left;width:100%;color:#000000;background-color:#ffffff;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;border-radius:0px;border-color:#000000;line-height:155%">
296+
style="max-width:600px;align:left;width:100%;color:#000000;background-color:#ffffff;border-radius:0px;border-color:#000000;line-height:155%">
297297
<tbody>
298298
<tr style="width:100%">
299-
<td>
299+
<td
300+
style="padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px">
300301
<p
301302
style="margin:0;padding:0;font-size:1em;padding-top:0.5em;padding-bottom:0.5em">
302303
Hello world
@@ -1594,10 +1595,11 @@ describe('Container Node', () => {
15941595
cellpadding="0"
15951596
cellspacing="0"
15961597
role="presentation"
1597-
style="max-width:600px;align:left;width:100%;color:#000000;background-color:#ffffff;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;border-radius:0px;border-color:#000000;line-height:155%">
1598+
style="max-width:600px;align:left;width:100%;color:#000000;background-color:#ffffff;border-radius:0px;border-color:#000000;line-height:155%">
15981599
<tbody>
15991600
<tr style="width:100%">
1600-
<td>
1601+
<td
1602+
style="padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px">
16011603
<p
16021604
style="margin:0;padding:0;font-size:1em;padding-top:0.5em;padding-bottom:0.5em">
16031605
Inside container

‎packages/react-email/src/cli/commands/testing/export.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ test('email export', { retry: 3 }, async () => {
5454
cellpadding="0"
5555
cellspacing="0"
5656
role="presentation"
57-
style="max-width:465px;margin-right:auto;margin-left:auto;margin-bottom:40px;margin-top:40px;border-radius:0.25rem;border-style:solid;border-width:1px;border-color:rgb(234,234,234);padding:20px">
57+
style="max-width:465px;margin-right:auto;margin-left:auto;margin-bottom:40px;margin-top:40px;border-radius:0.25rem;border-style:solid;border-width:1px;border-color:rgb(234,234,234)">
5858
<tbody>
5959
<tr style="width:100%">
60-
<td>
60+
<td style="padding:20px">
6161
<table
6262
align="center"
6363
width="100%"

‎packages/react-email/src/components/container/container.tsx‎

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,35 @@ import * as React from 'react';
33
export type ContainerProps = Readonly<React.ComponentPropsWithoutRef<'table'>>;
44

55
export const Container = React.forwardRef<HTMLTableElement, ContainerProps>(
6-
({ children, style, ...props }, ref) => {
6+
({ children, style = {}, ...props }, ref) => {
7+
// Split padding styles to improve compatibility with Klavyio and Outlook,
8+
// while preserving user-provided style property order without allocating
9+
// entry arrays on each render.
10+
const tdStyle: React.CSSProperties = {};
11+
const tableStyle: React.CSSProperties = {};
12+
13+
const styleRecord = style as Record<string, unknown>;
14+
15+
for (const key in styleRecord) {
16+
if (!Object.prototype.hasOwnProperty.call(styleRecord, key)) {
17+
continue;
18+
}
19+
20+
const value = styleRecord[key];
21+
22+
if (
23+
key === 'padding' ||
24+
key === 'paddingTop' ||
25+
key === 'paddingRight' ||
26+
key === 'paddingBottom' ||
27+
key === 'paddingLeft'
28+
) {
29+
(tdStyle as Record<string, unknown>)[key] = value;
30+
} else {
31+
(tableStyle as Record<string, unknown>)[key] = value;
32+
}
33+
}
34+
735
return (
836
<table
937
align="center"
@@ -14,11 +42,11 @@ export const Container = React.forwardRef<HTMLTableElement, ContainerProps>(
1442
cellSpacing="0"
1543
ref={ref}
1644
role="presentation"
17-
style={{ maxWidth: '37.5em', ...style }}
45+
style={{ maxWidth: '37.5em', ...tableStyle }}
1846
>
1947
<tbody>
2048
<tr style={{ width: '100%' }}>
21-
<td>{children}</td>
49+
<td style={tdStyle}>{children}</td>
2250
</tr>
2351
</tbody>
2452
</table>

‎packages/react-email/src/components/section/section.tsx‎

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,35 @@ import * as React from 'react';
33
export type SectionProps = Readonly<React.ComponentPropsWithoutRef<'table'>>;
44

55
export const Section = React.forwardRef<HTMLTableElement, SectionProps>(
6-
({ children, style, ...props }, ref) => {
6+
({ children, style = {}, ...props }, ref) => {
7+
// Split padding styles to improve compatibility with Klavyio and Outlook,
8+
// while preserving user-provided style property order without allocating
9+
// entry arrays on each render.
10+
const tdStyle: React.CSSProperties = {};
11+
const tableStyle: React.CSSProperties = {};
12+
13+
const styleRecord = style as Record<string, unknown>;
14+
15+
for (const key in styleRecord) {
16+
if (!Object.prototype.hasOwnProperty.call(styleRecord, key)) {
17+
continue;
18+
}
19+
20+
const value = styleRecord[key];
21+
22+
if (
23+
key === 'padding' ||
24+
key === 'paddingTop' ||
25+
key === 'paddingRight' ||
26+
key === 'paddingBottom' ||
27+
key === 'paddingLeft'
28+
) {
29+
(tdStyle as Record<string, unknown>)[key] = value;
30+
} else {
31+
(tableStyle as Record<string, unknown>)[key] = value;
32+
}
33+
}
34+
735
return (
836
<table
937
align="center"
@@ -14,11 +42,11 @@ export const Section = React.forwardRef<HTMLTableElement, SectionProps>(
1442
role="presentation"
1543
{...props}
1644
ref={ref}
17-
style={style}
45+
style={tableStyle}
1846
>
1947
<tbody>
2048
<tr>
21-
<td>{children}</td>
49+
<td style={tdStyle}>{children}</td>
2250
</tr>
2351
</tbody>
2452
</table>

‎packages/ui/src/utils/get-email-component.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ describe('getEmailComponent()', () => {
6464
cellpadding="0"
6565
cellspacing="0"
6666
role="presentation"
67-
style="max-width:465px;margin-right:auto;margin-left:auto;margin-bottom:40px;margin-top:40px;border-radius:0.25rem;border-style:solid;border-width:1px;border-color:rgb(234,234,234);padding:20px">
67+
style="max-width:465px;margin-right:auto;margin-left:auto;margin-bottom:40px;margin-top:40px;border-radius:0.25rem;border-style:solid;border-width:1px;border-color:rgb(234,234,234)">
6868
<tbody>
6969
<tr style="width:100%">
70-
<td>
70+
<td style="padding:20px">
7171
<table
7272
align="center"
7373
width="100%"

0 commit comments

Comments
 (0)