Email Editor
The Email Editor lets admins compose email templates that send automatically during workflows: welcome emails, reminders, acceptance letters, etc. It is a two-panel modal. The editor (subject, formatting toolbar, body) sits on the left. A live preview on the right shows how the email looks to recipients. Templates support variable injection with {{variable}} syntax. Drop in something like {{user.full_name}} and it is replaced with real values when the workflow runs. The preview also shows the email on desktop, mobile, and as plain text. Opens from the Workflow Editor when configuring an Email node.
Overview
The Email Editor is a stateless component. It receives template data and available variables as props, and emits changes via callbacks. It does not persist data. The parent (Workflow Editor) handles saving. It renders as a Dialog/modal, not a full page.
Dialog/modal, not a standalone page
Stateless. Parent owns data, editor emits changes
Workflow Editor → Email node → Configure
Layout Anatomy
Email Editor
Subject field
Body editor
Live preview
Interactive States
Switch between states to see how the Email Editor behaves in each scenario. The mockup below is a fully styled replica.
Email Editor
Type Here
Preview will appear here
Variable System
Variables use {{variable.name}} syntax (double curly braces). They are highlighted inline in the editor and substituted with sample values in the preview.
Dear {{user.full_name}}
Dear {{non existent variable}}
Dear Jane Doe
name
stringe.g. user.full_namesample
stringe.g. "Jane Doe"description
string (optional)tooltip text for the variableFormatting Toolbar
The editor uses Markdown syntax. Formatting buttons insert markdown markers around selected text.
S̶ Strikethrough
~~text~~U̲ Underline
Ctrl+UI Italic
*text*Ctrl+IB Bold
**text**Ctrl+B🔗 Link
[text](url)Ctrl+K≡ Bullet list
- item≡ Numbered list
1. item" Blockquote
> text+ / − Variable picker
toggles variable dropdownButton size
28 × 28pxButton radius
4pxDefault bg
transparentActive bg
#FDEEE8primaryLightActive color
#E8541AprimaryInteraction Flows
Save Flow
Edit
Admin edits subject or body → Save button becomes enabled
Save
Admin clicks Save → button shows loading state, disabled
Success
Brief "Saved" confirmation, button resets
Error
Error message shown, button re-enables
Cancel with Unsaved Changes
Dirty
Admin edits content (dirty state)
Cancel
Admin clicks Cancel
Confirm
Dialog: "Discard changes?" with [Keep editing] and [Discard]
Discard
Editor closes, changes lost
Keep
Dialog closes, editor stays open
Send Test Email
Click
Admin clicks "Send Test" button
Input
Panel appears with email input field
Send
Admin types email, clicks "Send" → loading state
Success
"Test email sent!" message, panel closes after 2s
Callback
onTest callback fires with { template, recipientEmail }
Props Interface
template
Object{ subject: string, body: string }variables
Array[{ name, sample, description }]onChange
Function(template) => voidonSave
Function(template) => voidonCancel
Function() => voidonTest
Function({ template, recipientEmail }) => voidComponent Map
EmailEditor
Root component. Manages local state, wires sub-components.TemplateEditor
Left panel. Subject field, formatting toolbar, body editor.FormattingToolbar
Toolbar row. Formatting buttons + variable picker trigger.VariablePicker
Dropdown list of available variables. Inserts on click.PreviewSystem
Right panel. Mode toggle + live preview frame.PreviewFrame
Rendered preview. Handles desktop/mobile/text modes.SendTestPanel
Inline panel for entering test recipient email.Code
import { Dialog } from '@mui/material';
import EmailEditor from '@/components/EmailEditor';
// Inside WorkflowEditor:
<Dialog open={emailNodeOpen} maxWidth="lg" fullWidth>
<EmailEditor
template={selectedNode.template}
variables={workflowVariables}
onSave={(template) => {
updateNode(selectedNode.id, { template });
setEmailNodeOpen(false);
}}
onCancel={() => setEmailNodeOpen(false)}
onTest={({ template, recipientEmail }) => {
sendTestEmail({ template, recipientEmail, workflowId });
}}
/>
</Dialog>