Skip to main content

EmailTheming extension

The EmailTheming extension from @react-email/editor/plugins adds theme-aware styling to the editor and provides a SerializerPlugin for theme-aware HTML export.
import { EmailTheming } from '@react-email/editor/plugins';

const extensions = [StarterKit, EmailTheming.configure({ theme: 'basic' })];
theme
EditorThemeInput
default:"'basic'"
The active theme. Accepts a built-in preset ('basic' or 'minimal') or a ThemeConfig object for custom themes.

Types

EditorTheme

type EditorTheme = 'basic' | 'minimal';

EditorThemeInput

The widened theme type accepted by the theme prop and EmailTheming.configure():
type EditorThemeInput = EditorTheme | ThemeConfig;

ThemeableComponent

The subset of KnownThemeComponents that can be customized via ThemeComponentStyles:
type ThemeableComponent =
  | 'body'
  | 'container'
  | 'h1'
  | 'h2'
  | 'h3'
  | 'link'
  | 'image'
  | 'button'
  | 'codeBlock'
  | 'inlineCode';

ThemeComponentStyles

CSS-in-JS styles keyed by themeable component name:
type ThemeComponentStyles = {
  [K in ThemeableComponent]?: React.CSSProperties & {
    align?: 'center' | 'left' | 'right';
  };
};

ThemeConfig

A custom theme configuration object:
interface ThemeConfig {
  extends?: EditorTheme;
  styles: ThemeComponentStyles;
}
extends
EditorTheme
The built-in theme to inherit from. If omitted, uses 'minimal' reset styles as a base.
styles
ThemeComponentStyles
required
CSS-in-JS styles keyed by component name. Values are merged on top of the base theme.

KnownThemeComponents

All component keys that a theme can style:
type KnownThemeComponents =
  | 'reset'
  | 'body'
  | 'container'
  | 'h1'
  | 'h2'
  | 'h3'
  | 'paragraph'
  | 'list'
  | 'listItem'
  | 'listParagraph'
  | 'nestedList'
  | 'blockquote'
  | 'codeBlock'
  | 'inlineCode'
  | 'link'
  | 'button'
  | 'section'
  | 'footer'
  | 'hr'
  | 'image';

KnownCssProperties

CSS properties that can be customized per theme component: Layout: align, width, height, padding, paddingTop, paddingRight, paddingBottom, paddingLeft, margin, marginTop, marginRight, marginBottom, marginLeft Appearance: backgroundColor, color, borderRadius, borderWidth, borderColor, borderStyle Typography: fontSize, fontWeight, lineHeight, textDecoration, fontFamily, letterSpacing

CssJs

A mapping of theme component keys to CSS properties:
type CssJs = Partial<Record<KnownThemeComponents, React.CSSProperties>>;

PanelGroup

Represents a group of configurable theme properties for a component:
interface PanelGroup {
  id: string;
  title: string;
  headerSlot?: React.ReactNode;
  classReference?: string;
  inputs: PanelInputProperty[];
}

PanelInputProperty

An individual configurable CSS property within a panel:
interface PanelInputProperty {
  label: string;
  type: 'text' | 'number' | 'color' | 'select';
  value: string;
  prop: string;
  classReference: string;
  unit?: string;
  options?: { label: string; value: string }[];
  placeholder?: string;
  category?: string;
}

Theme helpers

createTheme

Creates a custom theme from scratch (uses minimal reset as base):
import { createTheme } from '@react-email/editor/plugins';

const theme = createTheme({
  body: { backgroundColor: '#1a1a2e', color: '#e2e8f0' },
  button: { backgroundColor: '#3b82f6', color: '#fff' },
});
styles
ThemeComponentStyles
required
CSS-in-JS styles keyed by component name.
Returns a ThemeConfig object.

extendTheme

Extends a built-in theme with style overrides:
import { extendTheme } from '@react-email/editor/plugins';

const theme = extendTheme('basic', {
  body: { backgroundColor: '#eff6ff' },
  button: { backgroundColor: '#2563eb', borderRadius: '6px' },
});
base
EditorTheme
required
The built-in theme to extend ('basic' or 'minimal').
overrides
ThemeComponentStyles
required
CSS-in-JS styles to merge on top of the base theme.
Returns a ThemeConfig object.

Utility functions

getMergedCssJs

Merges the base theme styles with custom panel overrides:
import { getMergedCssJs } from '@react-email/editor/plugins';

const mergedStyles = getMergedCssJs(theme, panelStyles);
theme
EditorTheme
required
The active theme to use as a base.
panelStyles
PanelGroup[]
Custom style overrides from the theme panel UI.

getResolvedNodeStyles

Resolves the final CSS styles for a specific node based on theme and document depth:
import { getResolvedNodeStyles } from '@react-email/editor/plugins';

const styles = getResolvedNodeStyles(node, depth, mergedCssJs);
node
JSONContent
required
The TipTap node to resolve styles for.
depth
number
required
The node’s depth in the document tree. Affects styles for nested elements (e.g., nested lists).
mergedCssJs
CssJs
required
The merged theme styles from getMergedCssJs.

getThemeComponentKey

Maps a node type and depth to a theme component key:
import { getThemeComponentKey } from '@react-email/editor/plugins';

const paragraphKey = getThemeComponentKey('paragraph', 0); // 'paragraph'
const nestedListKey = getThemeComponentKey('bulletList', 2); // 'nestedList'

stylesToCss

Converts a theme’s style definitions to a CSS object:
import { stylesToCss } from '@react-email/editor/plugins';

const css = stylesToCss(styles, theme);

useEmailTheming

React hook that provides access to the current theme state from within the editor:
import { useEmailTheming } from '@react-email/editor/plugins';

function MyComponent() {
  const theming = useEmailTheming(editor);
  // Access theming.styles, theming.theme, theming.css
}