Skip to content

fix(editor): keep the default theme import in EmailEditor's published output - #3708

Merged
dielduarte merged 5 commits into
resend:canaryfrom
dudusotero:fix/editor-theme-css-import
Aug 25, 2026
Merged

fix(editor): keep the default theme import in EmailEditor's published output#3708
dielduarte merged 5 commits into
resend:canaryfrom
dudusotero:fix/editor-theme-css-import

Conversation

@dudusotero

@dudusotero dudusotero commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

EmailEditor is documented as importing @react-email/editor/themes/default.css on its own, and src/email-editor/email-editor.tsx has import '../ui/themes/default.css' for that. The import never reaches the published package: tsdown extracts the CSS into dist/style.css, drops the import from dist/index.mjs / dist/index.cjs, and dist/style.css is not in exports, so nothing can load it. Every published version ships this way, so <EmailEditor /> renders an unstyled bubble menu and slash command menu unless the app imports the theme itself. #3637 reported the orphan dist/style.css; #3638 removed the dangling ./styles/* export entries but the stylesheet is still unreachable. apps/web does not hit this because apps/web/src/app/editor/layout.tsx imports the theme explicitly.

css: { inject: true } from @tsdown/css is not enough here: it keeps the import in the ESM output but also writes a literal import './style.css' into the .cjs file, which breaks the CJS entry. This PR instead adds a small Rolldown plugin to tsdown.config.ts that treats every CSS import under src/ as external and rewrites it to the matching public entry from package.json exports. ../ui/themes/default.css becomes @react-email/editor/themes/default.css, which scripts/copy-css.ts already emits into dist/. The build now produces:

dist/index.mjs:  import "@react-email/editor/themes/default.css";
dist/index.cjs:  require("@react-email/editor/themes/default.css");

Only the root entry gets the import; the other subpaths are unchanged, dist/style.css is no longer emitted, and importing a CSS file that has no exports entry fails the build with a message pointing at the import. Nothing under src/ changes.

One consequence to be aware of: Jest setups without a CSS moduleNameMapper, and plain Node scripts importing @react-email/editor without a bundler, will now hit the CSS import on the root entry. If keeping the theme opt-in is preferred, the alternative is to remove the import from email-editor.tsx, stop emitting dist/style.css, and update the docs; I can switch the PR to that.

Test plan

  • pnpm build (with dts) and pnpm typecheck in packages/editor pass
  • pnpm test:unit: 50 files, 502 tests pass
  • biome check clean
  • Packed the build with pnpm pack and installed it in a Vite + React 19 app with no CSS import of its own: Vite loads ui/themes/default.css from the package and the menus render styled. The same app renders unstyled against the published 1.7.2.

Summary by cubic

Ships the default theme CSS with EmailEditor so bubble and slash menus are styled by default. The build now keeps the import in both ESM and CJS by rewriting CSS imports to exported subpaths; previously the import was extracted to an unexported file and menus rendered unstyled unless apps imported @react-email/editor/themes/default.css.

  • Review and migration
    • Confirm package.json exports include ./themes/default.css and that only the root entry imports it.
    • No dist/style.css is emitted; the build fails if a CSS import lacks an exports entry.
    • Jest or plain Node consumers must handle CSS imports (stub/map .css); bundler apps need no changes.

Written for commit f2c34fb. Summary will update on new commits.

Review in cubic

@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c12b89a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

@dudusotero is attempting to deploy a commit to the resend Team on Vercel.

A member of the Team first needs to authorize it.

@dudusotero
dudusotero changed the base branch from main to canary August 17, 2026 22:35
@github-actions github-actions Bot added the linear-synced PR has been synced to Linear label Aug 18, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@react-email/editor@3708

commit: f2c34fb

dielduarte and others added 3 commits August 25, 2026 15:08
…port

The build-time fix (tsdown plugin to keep the CSS import alive in the
published output) breaks require()/import() of the package's own entry
point for any consumer without a CSS-aware bundler in the loop (plain
Node scripts, Jest without a CSS moduleNameMapper) — it doesn't just
render unstyled anymore, it fails to load at all.

EmailEditor has always shipped this way in every published version;
the docs claimed otherwise. Correct the docs to match the real,
intentional behavior instead: EmailEditor works out of the box but is
unstyled by default, and the theme is a separate opt-in import — the
same pattern the lower-level composable API already documents, and
the same pattern resend.com/blog/react-email-6 describes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-email Ready Ready Preview Aug 25, 2026 6:21pm
react-email-demo Ready Ready Preview Aug 25, 2026 6:21pm

Request Review

@dielduarte

Copy link
Copy Markdown
Contributor

Hey @dudusotero thanks for the help! We have decided that this is a docs issue, and the default should come unstyled. I'm fixing the docs here and will merge this PR as your contribution. thank you!

@dielduarte
dielduarte merged commit e1f2a9a into resend:canary Aug 25, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

linear-synced PR has been synced to Linear

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants