4 new Playwright email templates with shadcn/ui — and how to make shadcn work in email

posted 2 min read

What is this?

@playwright-labs/reporter-email is a Playwright reporter that emails your team the test results after each CI run. This release adds 4 new templates built on shadcn/ui.

The core challenge

shadcn/ui is not email-compatible out of the box. Three things break:

  1. Radix UI — shadcn uses Radix for interactive behaviour (Select, Dialog, etc.). Radix calls browser APIs (window, document) at import time. @react-email/render runs in Node.js with none of these.
  2. CSS variables — shadcn default config generates hsl(var(--foreground)). Email clients don't support CSS variables.
  3. JSX transform conflict — in a Playwright project, esbuild replaces React's JSX with Playwright's own internal representation. That breaks @react-email/render.

Fixes

Radix: Rewrote all primitives as plain HTML. SelectItem is a <div> with a conditional span. Button is an <a> tag. No Radix import anywhere.

CSS variables: Set "cssVariables": false in components.json. shadcn then generates bg-slate-900 (concrete value) instead of bg-background (CSS variable).

JSX transform: Added /* @jsxImportSource react */ pragma to every .tsx component file. esbuild respects per-file pragma overrides, so React's JSX runtime is used instead of Playwright's.

New templates

base-chart — pass-rate bar

import { PlaywrightReportShadcnChartEmail }
  from "@playwright-labs/reporter-email/templates/shadcn/base-chart";

<PlaywrightReportShadcnChartEmail result={result} testCases={testCases} >

Adds a stacked horizontal bar showing the percentage of passed / failed / skipped tests. Pure CSS, no images.

import { PlaywrightReportShadcnButtonEmail }
  from "@playwright-labs/reporter-email/templates/shadcn/base-button";

<PlaywrightReportShadcnButtonEmail
  result={result}
  testCases={testCases}
  reportUrl="https://ci.example.com/report/42"
>

A footer with "View Full Report" and optionally "View N Failure(s)". Buttons are <a> tags styled with shadcn button variants.

base-themes — 6 color themes

import { PlaywrightReportShadcnThemesEmail }
  from "@playwright-labs/reporter-email/templates/shadcn/base-themes";

<PlaywrightReportShadcnThemesEmail result={result} testCases={testCases} theme="green" >

Themes: slate | zinc | rose | blue | green | orange. Each changes the accent bar, headings, and row backgrounds.

Import only what you need

Each template is a separate bundle under dist/templates/shadcn/. Individual imports:

// Only loads base-select bundle, nothing else
import { PlaywrightReportShadcnSelectEmail }
  from "@playwright-labs/reporter-email/templates/shadcn/base-select";

Or use the barrel for multiple templates:

import {
  PlaywrightReportShadcnChartEmail,
  PlaywrightReportShadcnThemesEmail,
} from "@playwright-labs/reporter-email/templates/shadcn";

Requires "moduleResolution": "bundler" in tsconfig.json to resolve the exports subpaths.

Run the preview locally

git clone https://github.com/vitalics/playwright-labs
cd playwright-labs && pnpm install
pnpm --filter @playwright-labs/reporter-email build
cd packages/reporter-email/examples && pnpm email:preview

Opens at http://localhost:3000. Edit any file in emails/ and the server hot-reloads.


GitHub: https://github.com/vitalics/playwright-labs

npm: @playwright-labs/reporter-email

1 Comment

0 votes
1

More Posts

5 Things This Playwright SQL Fixture Does So You Don't Have To

vitalicset - Apr 13

How I Built a React Portfolio in 7 Days That Landed ₹1.2L in Freelance Work

Dharanidharan - Feb 9

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

Angular-Aware E2E Testing: Query Components by @Input and Signals in Playwright

vitalicset - Apr 2

Why Email-Only Contact Forms Are Failing in 2026 (And What Developers Should Do Instead)

JayCode - Mar 2
chevron_left

Related Jobs

View all jobs →

Commenters (This Week)

4 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!