From c1fdee4ec46199478857221dcbd2ea3c11c5f2d0 Mon Sep 17 00:00:00 2001 From: makerprism-bot <261184658+makerprism-bot@users.noreply.github.com> Date: Sun, 19 Apr 2026 02:57:28 +0000 Subject: [PATCH] feat: Add configurable body background to Render.render_email Add optional body_background parameter to Render.render_email to allow customizing the element's background color. This enables the common transactional email pattern of tinted page backgrounds with lighter content cards inside. - Add ?body_background:Color.t parameter (defaults to solid white) - Generate proper background styles using Color.to_style - For gradients, add bgcolor attribute with fallback color for Outlook - Backward compatible: defaults to existing behavior Co-Authored-By: Claude Sonnet 4.6 --- lib/render.ml | 21 ++++++++++++++++++--- lib/render.mli | 8 +++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/render.ml b/lib/render.ml index 6818a85..7a4e263 100644 --- a/lib/render.ml +++ b/lib/render.ml @@ -14,7 +14,7 @@ let render_html element = let size_kb = size / 1024 in Error (Printf.sprintf "Email size %dKB exceeds Gmail's 102KB limit" size_kb) -let render_email element = +let render_email ?(body_background = Color.solid "#ffffff") element = (* Render the body content *) let body_html = Element.to_html element in @@ -24,6 +24,21 @@ let render_email element = let size_kb = size / 1024 in Error (Printf.sprintf "Email size %dKB exceeds Gmail's 102KB limit" size_kb) else + (* Build body background style and attributes *) + let background_style = Color.to_style body_background in + let base_style = "margin: 0; padding: 0; word-spacing: normal;" in + let full_style = base_style ^ " " ^ background_style in + + (* Add bgcolor attribute for Outlook gradient fallback *) + let bgcolor_attr = match body_background with + | Color.Solid hex -> Printf.sprintf " bgcolor=\"%s\"" hex + | Color.Gradient {fallback = Color.Solid fb_hex; _} -> + Printf.sprintf " bgcolor=\"%s\"" fb_hex + | Color.Gradient {fallback = Gradient _; _} -> + (* Should be impossible through API, but handle gracefully *) + " bgcolor=\"#ffffff\"" + in + (* Build complete email document *) let email_html = Printf.sprintf {| @@ -49,8 +64,8 @@ let render_email element = - + %s -|} body_html in +|} bgcolor_attr full_style body_html in Ok email_html diff --git a/lib/render.mli b/lib/render.mli index 395d130..705e778 100644 --- a/lib/render.mli +++ b/lib/render.mli @@ -28,10 +28,16 @@ val render_html : Element.t -> (string, string) Result.t Includes doctype, HTML wrapper, and email-specific meta tags. Checks Gmail 102KB limit before returning. + @param body_background Optional background color for the element. + Defaults to solid white (#ffffff). + Gradients are supported with proper fallback. @param element The email body content @return Ok complete email HTML on success, Error message if limit exceeded *) -val render_email : Element.t -> (string, string) Result.t +val render_email : + ?body_background:Color.t -> + Element.t -> + (string, string) Result.t (** Gmail size limit in bytes (102KB) *) val gmail_limit_bytes : int