diff --git a/apps/docs/editor/advanced/custom-extensions.mdx b/apps/docs/editor/advanced/custom-extensions.mdx index 2ec990f065..bd2dbbbdd1 100644 --- a/apps/docs/editor/advanced/custom-extensions.mdx +++ b/apps/docs/editor/advanced/custom-extensions.mdx @@ -279,3 +279,13 @@ const CustomParagraph = Paragraph.extend({ }, }); ``` + +## Examples + +See custom extensions in action with a runnable example: + + + + Custom Callout node with EmailNode.create, toolbar insertion, and bubble menu. + + diff --git a/apps/docs/editor/features/bubble-menu.mdx b/apps/docs/editor/features/bubble-menu.mdx index b0560d0242..4c9f4c9fcd 100644 --- a/apps/docs/editor/features/bubble-menu.mdx +++ b/apps/docs/editor/features/bubble-menu.mdx @@ -152,3 +152,16 @@ Control where the bubble menu appears relative to the selection. Distance from the selection in pixels. + +## Examples + +See bubble menus in action with runnable examples: + + + + Default bubble menu with text selection. + + + Composing a custom menu from primitives. + + diff --git a/apps/docs/editor/features/buttons.mdx b/apps/docs/editor/features/buttons.mdx index f4dfdde3b0..9d8497e3a1 100644 --- a/apps/docs/editor/features/buttons.mdx +++ b/apps/docs/editor/features/buttons.mdx @@ -81,3 +81,13 @@ function Toolbar() { ); } ``` + +## Examples + +See buttons in action with a runnable example: + + + + Button insertion and editing with the button bubble menu. + + diff --git a/apps/docs/editor/features/column-layouts.mdx b/apps/docs/editor/features/column-layouts.mdx index ad77d6f90c..5d18533c3b 100644 --- a/apps/docs/editor/features/column-layouts.mdx +++ b/apps/docs/editor/features/column-layouts.mdx @@ -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: + + + + Toolbar-driven 2/3/4 column insertion. + + diff --git a/apps/docs/editor/features/email-export.mdx b/apps/docs/editor/features/email-export.mdx index 47e422ac50..be356e5004 100644 --- a/apps/docs/editor/features/email-export.mdx +++ b/apps/docs/editor/features/email-export.mdx @@ -185,3 +185,16 @@ export function FullEmailBuilder() { ); } ``` + +## Examples + +See email export in action with runnable examples: + + + + Export editor content to themed HTML. + + + Complete editor with theming, menus, and export. + + diff --git a/apps/docs/editor/features/link-editing.mdx b/apps/docs/editor/features/link-editing.mdx index 46b1e28c6a..9c2176876c 100644 --- a/apps/docs/editor/features/link-editing.mdx +++ b/apps/docs/editor/features/link-editing.mdx @@ -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: + + + + Inline link editing with Cmd+K support. + + diff --git a/apps/docs/editor/features/slash-commands.mdx b/apps/docs/editor/features/slash-commands.mdx index 8a07e015ab..6dd6c7a8f6 100644 --- a/apps/docs/editor/features/slash-commands.mdx +++ b/apps/docs/editor/features/slash-commands.mdx @@ -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: + + + + Default commands plus a custom Greeting command. + + diff --git a/apps/docs/editor/features/styling.mdx b/apps/docs/editor/features/styling.mdx index a50f5cb851..a275c1fb19 100644 --- a/apps/docs/editor/features/styling.mdx +++ b/apps/docs/editor/features/styling.mdx @@ -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. + +## Examples + +See styling and theming in action with runnable examples: + + + + Basic/Minimal theme toggle with live preview. + + + Complete editor with all styling features combined. + + diff --git a/apps/docs/editor/features/theming.mdx b/apps/docs/editor/features/theming.mdx index f9a914b3b2..cab05c4c4b 100644 --- a/apps/docs/editor/features/theming.mdx +++ b/apps/docs/editor/features/theming.mdx @@ -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: + + + + Basic/Minimal theme toggle with live preview. + + diff --git a/apps/docs/editor/getting-started.mdx b/apps/docs/editor/getting-started.mdx index c478c2695a..7ff54bff75 100644 --- a/apps/docs/editor/getting-started.mdx +++ b/apps/docs/editor/getting-started.mdx @@ -151,6 +151,25 @@ const content = ` ``` +## Examples + +See these features in action with runnable examples: + + + + The simplest possible editor setup. + + + EditorProvider with StarterKit and no overlays. + + + Theme toggle, HTML export, and JSON output. + + + Browse the complete set of interactive examples. + + + ## Next steps diff --git a/apps/docs/editor/overview.mdx b/apps/docs/editor/overview.mdx index c53b360429..6369a2fdde 100644 --- a/apps/docs/editor/overview.mdx +++ b/apps/docs/editor/overview.mdx @@ -61,3 +61,16 @@ The editor is organized into five entry points: Create your own email-compatible nodes. + +## Examples + +Runnable examples are available at [editor-examples.react.email](https://editor-examples.react.email). Each example demonstrates a specific feature in isolation: + + + + All features combined — theming, bubble menus, slash commands, and HTML export. + + + Browse the complete set of interactive examples. + + diff --git a/packages/editor/examples/README.md b/packages/editor/examples/README.md new file mode 100644 index 0000000000..01d52102ab --- /dev/null +++ b/packages/editor/examples/README.md @@ -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 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) diff --git a/packages/editor/examples/src/app.tsx b/packages/editor/examples/src/app.tsx index 2a1404a2d2..c9b89d67ca 100644 --- a/packages/editor/examples/src/app.tsx +++ b/packages/editor/examples/src/app.tsx @@ -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 (
- + {activeExample.docsUrl ? ( + + ) : null} +
); diff --git a/packages/editor/examples/src/examples/index.ts b/packages/editor/examples/src/examples/index.ts index cf2b09a5c4..af795af9aa 100644 --- a/packages/editor/examples/src/examples/index.ts +++ b/packages/editor/examples/src/examples/index.ts @@ -19,6 +19,7 @@ export interface ExampleItem { id: string; label: string; component: React.ComponentType; + docsUrl?: string; } export interface ExampleSection { @@ -34,27 +35,36 @@ export const sections: ExampleSection[] = [ id: 'one-line-editor', label: 'Minimal', component: OneLineEditor, + docsUrl: 'https://react.email/docs/editor/getting-started', }, { id: 'one-line-editor-full', label: 'Full Features', component: OneLineEditorFull, + docsUrl: 'https://react.email/docs/editor/getting-started', }, ], }, { title: 'Getting Started', examples: [ - { id: 'basic-editor', label: 'Basic Editor', component: BasicEditor }, + { + id: 'basic-editor', + label: 'Basic Editor', + component: BasicEditor, + docsUrl: 'https://react.email/docs/editor/getting-started', + }, { id: 'bubble-menu', label: 'Bubble Menu', component: BubbleMenuExample, + docsUrl: 'https://react.email/docs/editor/features/bubble-menu', }, { id: 'slash-commands', label: 'Slash Commands', component: SlashCommands, + docsUrl: 'https://react.email/docs/editor/features/slash-commands', }, ], }, @@ -65,17 +75,25 @@ export const sections: ExampleSection[] = [ id: 'custom-bubble-menu', label: 'Custom Bubble Menu', component: CustomBubbleMenu, + docsUrl: 'https://react.email/docs/editor/features/bubble-menu', + }, + { + id: 'link-editing', + label: 'Link Editing', + component: LinkEditing, + docsUrl: 'https://react.email/docs/editor/features/link-editing', }, - { id: 'link-editing', label: 'Link Editing', component: LinkEditing }, { id: 'column-layouts', label: 'Column Layouts', component: ColumnLayouts, + docsUrl: 'https://react.email/docs/editor/features/column-layouts', }, { id: 'buttons', label: 'Buttons', component: Buttons, + docsUrl: 'https://react.email/docs/editor/features/buttons', }, ], }, @@ -86,32 +104,43 @@ export const sections: ExampleSection[] = [ id: 'email-theming', label: 'Email Theming', component: EmailThemingExample, + docsUrl: 'https://react.email/docs/editor/features/theming', + }, + { + id: 'email-export', + label: 'Email Export', + component: EmailExport, + docsUrl: 'https://react.email/docs/editor/features/email-export', }, - { id: 'email-export', label: 'Email Export', component: EmailExport }, { id: 'custom-extensions', label: 'Custom Extensions', component: CustomExtensions, + docsUrl: 'https://react.email/docs/editor/advanced/custom-extensions', }, { id: 'inspector-defaults', label: 'Inspector — Defaults', component: InspectorDefaults, + docsUrl: 'https://react.email/docs/editor/overview', }, { id: 'inspector-composed', label: 'Inspector — Composed', component: InspectorComposed, + docsUrl: 'https://react.email/docs/editor/overview', }, { id: 'inspector-custom', label: 'Inspector — Custom', component: InspectorCustom, + docsUrl: 'https://react.email/docs/editor/overview', }, { id: 'full-email-builder', label: 'Full Email Builder', component: FullEmailBuilder, + docsUrl: 'https://react.email/docs/editor/features/email-export', }, ], }, diff --git a/packages/editor/examples/src/sidebar.tsx b/packages/editor/examples/src/sidebar.tsx index d70084243e..c390283a10 100644 --- a/packages/editor/examples/src/sidebar.tsx +++ b/packages/editor/examples/src/sidebar.tsx @@ -11,7 +11,7 @@ interface SidebarProps { export function Sidebar({ sections, activeId, onSelect }: SidebarProps) { return ( -