Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apps/docs/editor/advanced/custom-extensions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,13 @@ const CustomParagraph = Paragraph.extend({
},
});
```

## Examples

See custom extensions in action with a runnable example:

<CardGroup cols={2}>
<Card title="Custom Extensions" icon="code" href="https://editor-examples.react.email/#custom-extensions">
Custom Callout node with EmailNode.create, toolbar insertion, and bubble menu.
</Card>
</CardGroup>
13 changes: 13 additions & 0 deletions apps/docs/editor/features/bubble-menu.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,16 @@ Control where the bubble menu appears relative to the selection.
<ResponseField name="offset" type="number" default="8">
Distance from the selection in pixels.
</ResponseField>

## Examples

See bubble menus in action with runnable examples:

<CardGroup cols={2}>
<Card title="Bubble Menu" icon="code" href="https://editor-examples.react.email/#bubble-menu">
Default bubble menu with text selection.
</Card>
<Card title="Custom Bubble Menu" icon="code" href="https://editor-examples.react.email/#custom-bubble-menu">
Composing a custom menu from primitives.
</Card>
</CardGroup>
10 changes: 10 additions & 0 deletions apps/docs/editor/features/buttons.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,13 @@ function Toolbar() {
);
}
```

## Examples

See buttons in action with a runnable example:

<CardGroup cols={2}>
<Card title="Buttons" icon="code" href="https://editor-examples.react.email/#buttons">
Button insertion and editing with the button bubble menu.
</Card>
</CardGroup>
10 changes: 10 additions & 0 deletions apps/docs/editor/features/column-layouts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,13 @@ The default slash commands include column layouts. Type `/` and search for "colu
- **Four Columns**: `FOUR_COLUMNS`

See [Slash Commands](/editor/features/slash-commands) for setup details.

## Examples

See column layouts in action with a runnable example:

<CardGroup cols={2}>
<Card title="Column Layouts" icon="code" href="https://editor-examples.react.email/#column-layouts">
Toolbar-driven 2/3/4 column insertion.
</Card>
</CardGroup>
13 changes: 13 additions & 0 deletions apps/docs/editor/features/email-export.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,16 @@ export function FullEmailBuilder() {
);
}
```

## Examples

See email export in action with runnable examples:

<CardGroup cols={2}>
<Card title="Email Export" icon="code" href="https://editor-examples.react.email/#email-export">
Export editor content to themed HTML.
</Card>
<Card title="Full Email Builder" icon="code" href="https://editor-examples.react.email/#full-email-builder">
Complete editor with theming, menus, and export.
</Card>
</CardGroup>
10 changes: 10 additions & 0 deletions apps/docs/editor/features/link-editing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,13 @@ const content = `

The link extension is included in `StarterKit` with `openOnClick` disabled by default.
This means that clicking a link in edit mode focuses it rather than navigating away.

## Examples

See link editing in action with a runnable example:

<CardGroup cols={2}>
<Card title="Link Editing" icon="code" href="https://editor-examples.react.email/#link-editing">
Inline link editing with Cmd+K support.
</Card>
</CardGroup>
10 changes: 10 additions & 0 deletions apps/docs/editor/features/slash-commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,13 @@ This is useful when you want a minimal command palette. For example, only allowi
allow={({ editor }) => !editor.isActive('codeBlock')}
/>
```

## Examples

See slash commands in action with a runnable example:

<CardGroup cols={2}>
<Card title="Slash Commands" icon="code" href="https://editor-examples.react.email/#slash-commands">
Default commands plus a custom Greeting command.
</Card>
</CardGroup>
13 changes: 13 additions & 0 deletions apps/docs/editor/features/styling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,16 @@ Customize how content looks inside the editor.
Content styling in the editor (via `.tiptap` selectors) only affects how content looks while
editing. The exported email HTML is styled separately via the [Theming](/editor/features/theming) system.
</Tip>

## Examples

See styling and theming in action with runnable examples:

<CardGroup cols={2}>
<Card title="Email Theming" icon="code" href="https://editor-examples.react.email/#email-theming">
Basic/Minimal theme toggle with live preview.
</Card>
<Card title="Full Email Builder" icon="code" href="https://editor-examples.react.email/#full-email-builder">
Complete editor with all styling features combined.
</Card>
</CardGroup>
10 changes: 10 additions & 0 deletions apps/docs/editor/features/theming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,13 @@ const { html, text } = await composeReactEmail({ editor, preview: null });
```

See [Email Export](/editor/features/email-export) for more details on the serialization pipeline.

## Examples

See theming in action with a runnable example:

<CardGroup cols={2}>
<Card title="Email Theming" icon="code" href="https://editor-examples.react.email/#email-theming">
Basic/Minimal theme toggle with live preview.
</Card>
</CardGroup>
19 changes: 19 additions & 0 deletions apps/docs/editor/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,25 @@ const content = `
<EditorProvider extensions={extensions} content={content} />
```

## Examples

See these features in action with runnable examples:

<CardGroup cols={2}>
<Card title="Minimal One-Line Editor" icon="code" href="https://editor-examples.react.email/#one-line-editor">
The simplest possible editor setup.
</Card>
<Card title="Basic Editor" icon="code" href="https://editor-examples.react.email/#basic-editor">
EditorProvider with StarterKit and no overlays.
</Card>
<Card title="Full Features" icon="code" href="https://editor-examples.react.email/#one-line-editor-full">
Theme toggle, HTML export, and JSON output.
</Card>
<Card title="All Examples" icon="folder-open" href="https://editor-examples.react.email">
Browse the complete set of interactive examples.
</Card>
</CardGroup>

## Next steps

<EditorNextSteps />
13 changes: 13 additions & 0 deletions apps/docs/editor/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,16 @@ The editor is organized into five entry points:
Create your own email-compatible nodes.
</Card>
</CardGroup>

## Examples

Runnable examples are available at [editor-examples.react.email](https://editor-examples.react.email). Each example demonstrates a specific feature in isolation:

<CardGroup cols={2}>
<Card title="Full Email Builder" icon="code" href="https://editor-examples.react.email/#full-email-builder">
All features combined — theming, bubble menus, slash commands, and HTML export.
</Card>
<Card title="All Examples" icon="folder-open" href="https://editor-examples.react.email">
Browse the complete set of interactive examples.
</Card>
</CardGroup>
69 changes: 69 additions & 0 deletions packages/editor/examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# @react-email/editor examples

Interactive examples demonstrating the [React Email Editor](https://react.email/docs/editor/overview). Each example is a standalone component that showcases a specific feature or pattern.

**Live website:** [editor-examples.react.email](https://editor-examples.react.email)

## Running locally

From the repository root:

```sh
pnpm install
pnpm dev --filter editor-examples
```

Then open <http://localhost:5173> in your browser. Use the sidebar to navigate between examples.

## Examples

### One-Line Editor

| Example | Demo | Source | Docs |
|---------|------|--------|------|
| **Minimal** — Single `EmailEditor` with default wiring | [Live](https://editor-examples.react.email/#one-line-editor) | [`one-line-editor.tsx`](src/examples/one-line-editor.tsx) | [Getting Started](https://react.email/docs/editor/getting-started) |
| **Full Features** — Theme toggle, HTML export, JSON output | [Live](https://editor-examples.react.email/#one-line-editor-full) | [`one-line-editor-full.tsx`](src/examples/one-line-editor-full.tsx) | [Getting Started](https://react.email/docs/editor/getting-started) |

### Getting Started

| Example | Demo | Source | Docs |
|---------|------|--------|------|
| **Basic Editor** — `EditorProvider` with `StarterKit` only | [Live](https://editor-examples.react.email/#basic-editor) | [`basic-editor.tsx`](src/examples/basic-editor.tsx) | [Getting Started](https://react.email/docs/editor/getting-started) |
| **Bubble Menu** — Default floating formatting toolbar | [Live](https://editor-examples.react.email/#bubble-menu) | [`bubble-menu.tsx`](src/examples/bubble-menu.tsx) | [Bubble Menu](https://react.email/docs/editor/features/bubble-menu) |
| **Slash Commands** — Command menu with custom commands | [Live](https://editor-examples.react.email/#slash-commands) | [`slash-commands.tsx`](src/examples/slash-commands.tsx) | [Slash Commands](https://react.email/docs/editor/features/slash-commands) |

### Intermediate

| Example | Demo | Source | Docs |
|---------|------|--------|------|
| **Custom Bubble Menu** — Composing a menu from primitives | [Live](https://editor-examples.react.email/#custom-bubble-menu) | [`custom-bubble-menu.tsx`](src/examples/custom-bubble-menu.tsx) | [Bubble Menu](https://react.email/docs/editor/features/bubble-menu) |
| **Link Editing** — Inline link editing with `Cmd+K` | [Live](https://editor-examples.react.email/#link-editing) | [`link-editing.tsx`](src/examples/link-editing.tsx) | [Link Editing](https://react.email/docs/editor/features/link-editing) |
| **Column Layouts** — Toolbar-driven 2/3/4 column insertion | [Live](https://editor-examples.react.email/#column-layouts) | [`column-layouts.tsx`](src/examples/column-layouts.tsx) | [Column Layouts](https://react.email/docs/editor/features/column-layouts) |
| **Buttons** — Button insertion and editing | [Live](https://editor-examples.react.email/#buttons) | [`images-and-buttons.tsx`](src/examples/images-and-buttons.tsx) | [Buttons](https://react.email/docs/editor/features/buttons) |

### Advanced

| Example | Demo | Source | Docs |
|---------|------|--------|------|
| **Email Theming** — Basic/Minimal theme toggle | [Live](https://editor-examples.react.email/#email-theming) | [`email-theming.tsx`](src/examples/email-theming.tsx) | [Email Theming](https://react.email/docs/editor/features/theming) |
| **Email Export** — HTML export via `composeReactEmail` | [Live](https://editor-examples.react.email/#email-export) | [`email-export.tsx`](src/examples/email-export.tsx) | [Email Export](https://react.email/docs/editor/features/email-export) |
| **Custom Extensions** — Custom Callout node with `EmailNode.create` | [Live](https://editor-examples.react.email/#custom-extensions) | [`custom-extensions.tsx`](src/examples/custom-extensions.tsx) | [Custom Extensions](https://react.email/docs/editor/advanced/custom-extensions) |
| **Inspector — Defaults** — Default inspector panels | [Live](https://editor-examples.react.email/#inspector-defaults) | [`inspector-defaults.tsx`](src/examples/inspector-defaults.tsx) | [Overview](https://react.email/docs/editor/overview) |
| **Inspector — Composed** — Composed inspector layout | [Live](https://editor-examples.react.email/#inspector-composed) | [`inspector-composed.tsx`](src/examples/inspector-composed.tsx) | [Overview](https://react.email/docs/editor/overview) |
| **Inspector — Custom** — Custom inspector UI | [Live](https://editor-examples.react.email/#inspector-custom) | [`inspector-custom.tsx`](src/examples/inspector-custom.tsx) | [Overview](https://react.email/docs/editor/overview) |
| **Full Email Builder** — All features combined | [Live](https://editor-examples.react.email/#full-email-builder) | [`full-email-builder.tsx`](src/examples/full-email-builder.tsx) | [Email Export](https://react.email/docs/editor/features/email-export) |

## Documentation

- [Editor Overview](https://react.email/docs/editor/overview)
- [Getting Started](https://react.email/docs/editor/getting-started)
- [Bubble Menu](https://react.email/docs/editor/features/bubble-menu)
- [Slash Commands](https://react.email/docs/editor/features/slash-commands)
- [Email Theming](https://react.email/docs/editor/features/theming)
- [Styling](https://react.email/docs/editor/features/styling)
- [Buttons](https://react.email/docs/editor/features/buttons)
- [Column Layouts](https://react.email/docs/editor/features/column-layouts)
- [Link Editing](https://react.email/docs/editor/features/link-editing)
- [Email Export](https://react.email/docs/editor/features/email-export)
- [Extensions](https://react.email/docs/editor/advanced/extensions)
- [Custom Extensions](https://react.email/docs/editor/advanced/custom-extensions)
35 changes: 31 additions & 4 deletions packages/editor/examples/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,42 @@ const allExamples = sections.flatMap((s) => s.examples);

export function App() {
const [activeId, setActiveId] = useHashRoute(allExamples[0].id);
const ActiveExample =
allExamples.find((e) => e.id === activeId)?.component ??
allExamples[0].component;
const activeExample =
allExamples.find((e) => e.id === activeId) ?? allExamples[0];
const ActiveComponent = activeExample.component;

return (
<div className="flex h-screen font-sans text-(--re-text)">
<Sidebar sections={sections} activeId={activeId} onSelect={setActiveId} />
<main className="flex-1 min-w-0 flex flex-col overflow-y-auto p-8">
<ActiveExample key={activeId} />
{activeExample.docsUrl ? (
<div className="flex justify-end mb-2">
<a
href={activeExample.docsUrl}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-(--re-text-muted) hover:text-(--re-text) transition-colors flex items-center gap-1"
>
Docs
<svg
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path
d="M3.5 2H2.5C1.95 2 1.5 2.45 1.5 3V9.5C1.5 10.05 1.95 10.5 2.5 10.5H9C9.55 10.5 10 10.05 10 9.5V8.5M7 1.5H10.5M10.5 1.5V5M10.5 1.5L5 7"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</a>
</div>
) : null}
<ActiveComponent key={activeId} />
</main>
</div>
);
Expand Down
Loading
Loading