From aa4f68f199710cca0a87beb5db9cc32eca1f7982 Mon Sep 17 00:00:00 2001
From: Arjun Komath
Date: Sat, 22 Aug 2026 11:39:28 +1000
Subject: [PATCH] fix email width for long content
---
web/lib/email/templates/base.tsx | 7 +++++-
web/tests/email-templates.test.tsx | 38 ++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 web/tests/email-templates.test.tsx
diff --git a/web/lib/email/templates/base.tsx b/web/lib/email/templates/base.tsx
index ebf66e2c..dd3c2e72 100644
--- a/web/lib/email/templates/base.tsx
+++ b/web/lib/email/templates/base.tsx
@@ -24,7 +24,7 @@ export function BaseEmail({ preview, children, baseUrl }: BaseEmailProps) {
{preview}
-
+
@@ -47,7 +47,9 @@ const container = {
margin: "0 auto",
padding: "12px 0 32px",
marginBottom: "64px",
+ width: "100%",
maxWidth: "600px",
+ tableLayout: "fixed" as const,
};
const header = {
@@ -56,6 +58,9 @@ const header = {
const content = {
padding: "16px 24px",
+ overflowWrap: "anywhere" as const,
+ wordBreak: "break-word" as const,
+ wordWrap: "break-word" as const,
};
const footer = {
diff --git a/web/tests/email-templates.test.tsx b/web/tests/email-templates.test.tsx
new file mode 100644
index 00000000..993e30d5
--- /dev/null
+++ b/web/tests/email-templates.test.tsx
@@ -0,0 +1,38 @@
+import { render } from "@react-email/render";
+import { describe, expect, it } from "vitest";
+import { Alert } from "@/lib/email/templates/alert";
+import { MemberInvitation } from "@/lib/email/templates/member-invitation";
+
+const longContent = "x".repeat(2_000);
+
+const templates = {
+ alert: Alert({
+ bannerText: "BUILD FAILED",
+ heading: "Build Failure Alert",
+ description: "The build failed.",
+ details: [{ label: "Error", value: longContent }],
+ }),
+ invitation: MemberInvitation({
+ inviterName: longContent,
+ role: "member",
+ inviteUrl: `https://cloud.example.com/invite/${longContent}`,
+ }),
+};
+
+describe("email templates", () => {
+ it.each(Object.entries(templates))(
+ "constrains and wraps long %s content",
+ async (_, template) => {
+ const html = await render(template);
+
+ expect(html).toContain(longContent);
+ expect(html).toContain('width="600"');
+ expect(html).toContain("width:100%");
+ expect(html).toContain("max-width:600px");
+ expect(html).toContain("table-layout:fixed");
+ expect(html).toContain("overflow-wrap:anywhere");
+ expect(html).toContain("word-break:break-word");
+ expect(html).toContain("word-wrap:break-word");
+ },
+ );
+});