fix(react-email): keep a longhand padding of 0 on Button

AB
3d ago
+35-4

Fixes #3792

Intent

Bug fix. <Button style={{ padding: '12px 20px', paddingTop: 0 }}> rendered with 12px of top padding, because the explicit 0 was dropped and the shorthand took over.

What was going on

parsePadding turned each side into px with a truthiness check:

paddingTop: paddingTop ? convertToPx(paddingTop) : undefined,

so the number 0 came back as undefined. Button spreads the user's style (which still contains padding: '12px 20px') and then the parsed longhands on top. React omits undefined style values, so the rendered <a> had

padding:12px 20px;padding-right:20px;padding-left:20px

with no padding-top at all. The Outlook spacer is computed from the parsed values with ?? 0, so it already treated the top as 0, which means Outlook and every other client disagreed about the button height. paddingTop: '0px' was fine because the string is truthy.

Changes

parsePadding now only skips undefined and the empty string, so 0 is converted like any other value. The empty string case keeps its existing behaviour (there is a test for it).

Verification

Two tests, both written before the fix and both failing on canary:

  • parsePadding({ padding: '12px 20px', paddingTop: 0 }) returned paddingTop: undefined, now 0.
  • Rendering the Button above now contains padding-top:0; and padding-bottom:0;.

vitest run in packages/react-email: 304 passed. The one failing test and two failing suites (cli/commands/testing/export*.spec.ts) fail the same way on a clean canary checkout in my environment, so they are unrelated. tsc --noEmit and biome check are clean.

Added a patch changeset for react-email.


Summary by cubic

Fixes <Button> dropping an explicit longhand padding of 0, so style={{ padding: '12px 20px', paddingTop: 0 }} now renders with no top padding instead of falling back to the shorthand's 12px.

parsePadding skipped falsy values, so 0 became undefined and React omitted it from the style, letting the shorthand win. It now only skips undefined and empty strings. Tests cover the parsing and the rendered output, and a patch changeset for react-email is included.