Skip to content

Show newsletter section descriptions inline and fix email dark-mode rendering - #1057

Merged
kevinhermawan merged 1 commit into
mainfrom
fix/email-section-descriptions-and-dark-mode
Jul 27, 2026
Merged

Show newsletter section descriptions inline and fix email dark-mode rendering#1057
kevinhermawan merged 1 commit into
mainfrom
fix/email-section-descriptions-and-dark-mode

Conversation

@kevinhermawan

Copy link
Copy Markdown
Contributor

Summary

Each newsletter section now explains itself under its own heading instead of deferring to a glossary box at the bottom of the email. Verifying that against real renders turned up three bugs in the shared shell that affect every template we send, so they are fixed here too: the card's shadow showed light bars in dark mode, the mobile top margin never collapsed, and no colored text could be restyled for dark mode at all.

Related issues

Closes #1056

Important changes

  • Section descriptions moved inline. The description sits between the heading and the rule. renderSectionGlossary and GLOSSARY_TITLE are gone, since keeping both would print the same sentences twice.
  • Copy rewritten in both languages. The old strings were padded to a 4-character band so the glossary box read as an even block, which made them stilted. They now describe what each section collects, and none of them mentions the "Read more" link, because every article already has one.
  • Card shadow no longer breaks in dark mode. The paper-stack effect painted two opaque light sheets (#ffffff, #f3f4f6). Clients that recolor the card leave box-shadow untouched, so those sheets survived as bright bars under a dark card. Every layer is now translucent black.
  • Mobile top margin actually collapses. max-sm:mt-0 was dead code: React Email's Tailwind serializes it as @media not all and(min-width:640px), which is invalid CSS that every client drops. Replaced with a hand-written media query keyed off an email-card class.
  • Dark palette for text, rules, and surfaces. The Tailwind transform rewrites text-ink and friends into inline styles and deletes the class names, so a media query had nothing to target. Every element carrying a color now also carries a marker class that survives the transform, and a prefers-color-scheme: dark block recolors it. Paired with color-scheme meta so Apple Mail and Outlook use the palette instead of force-inverting.

Two dark-mode bugs only appeared under render. Body paints the canvas colour twice, once on <body> and again on an inner full-width cell that carries no className, so the recoloured body was covered until the rule reached that cell as well. A border-color shorthand also flattened the callout's brand-blue left accent, now scoped to border-left-color.

Other changes

  • The confirm button in the pending-confirmation email inverts to light-on-dark. At #111827 on a dark card it would have been close to invisible.
  • The length test on section copy now checks a 30 to 75 character range, which is what matters once the text has to fit on one line under a heading. The old 4-character band existed only for the glossary box's even block.

Key files to review

  • packages/shared/email-templates/src/shared/email-shell.tsx - the marker classes, dark stylesheet, card shadow, and mobile rule. The three - Important: callouts explain why each workaround exists.
  • packages/shared/email-templates/src/newsletter/default-newsletter.tsx - renderSectionHeader and the rewritten SECTION_COPY.
  • packages/shared/email-templates/src/render-newsletter-email.test.tsx - two new tests: description placement and ordering, and a guard that the dark stylesheet plus every marker class survive rendering.

How to test

  1. pnpm --filter @workspace/email-templates test - 94 tests pass.
  2. pnpm --filter @workspace/email-templates email:dev and open newsletter-en and newsletter-id. Each section shows its description under the heading, above the rule, with no glossary box at the bottom.
  3. Narrow the browser below 640px. The card sits flush with the top. Above 640px it keeps its 32px top margin.
  4. For dark mode, export the HTML and swap @media (prefers-color-scheme:dark) for @media all, then open it. Confirm the canvas, card, headings, body copy, bylines, rules, and links all recolor, with no light bars under the card. Repeat for the three registration templates and check the callout accent and confirm button.
  5. pnpm code-quality from the repository root.

Notes for reviewers

Gmail is deliberately not covered. It supports none of the dark-mode hooks and its mobile apps auto-invert with no opt-out, so there is no way to hand it this palette. It keeps inverting the light one, which reads fine now that the bars are gone.

Move each newsletter section's explanation under its heading, above the
rule, and drop the closing glossary box that repeated the same copy.
Rewrite the descriptions in both languages so they describe the section
rather than the UI.

Fix three rendering bugs found while verifying. The card's paper-stack
shadow painted opaque white sheets that survived a client's dark-mode
recolor and showed as bright bars under the card. The mobile top margin
never collapsed because React Email serializes max-sm: variants as
invalid CSS. Colored text could not be restyled for dark mode at all,
since the Tailwind transform rewrites utilities to inline styles and
drops the class names.
@kevinhermawan
kevinhermawan merged commit 61fbc96 into main Jul 27, 2026
40 of 41 checks passed
@kevinhermawan
kevinhermawan deleted the fix/email-section-descriptions-and-dark-mode branch July 27, 2026 05:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show newsletter section descriptions inline and fix email dark-mode rendering

2 participants