Command menu triggered by typing a character (default: /).
SlashCommand.Root
import { defaultSlashCommands, SlashCommand } from '@react-email/editor/ui';
<SlashCommand.Root items={defaultSlashCommands} />
items
SlashCommandItem[]
default:"defaultSlashCommands"
Array of commands to display. Falls back to defaultSlashCommands when not provided.
filterItems
(items, query, editor) => SlashCommandItem[]
Custom filter function. By default, uses fuzzy matching on title, description, and search terms.
Character that triggers the command menu.
allow
(props: { editor }) => boolean
Controls when the menu can appear. Return false to prevent it.
children
(props: SlashCommandRenderProps) => ReactNode
Custom render function for the command list. Receives items, query, selectedIndex, and onSelect.
Custom rendering
Use the children render function to fully customize how the command list looks.
The render function receives the filtered items, current query, selected index,
and a callback to select an item:
import { defaultSlashCommands, SlashCommand } from '@react-email/editor/ui';
<SlashCommand.Root items={defaultSlashCommands}>
{({ items, query, selectedIndex, onSelect }) => (
<div className="my-command-list">
{items.map((item, index) => (
<button
key={item.title}
onClick={() => onSelect(index)}
data-selected={index === selectedIndex}
className="my-command-item"
>
{item.icon}
<div>
<span>{item.title}</span>
<span>{item.description}</span>
</div>
</button>
))}
{items.length === 0 && (
<div className="my-command-empty">
No results for "{query}"
</div>
)}
</div>
)}
</SlashCommand.Root>
Custom commands
Pass your own items to add domain-specific commands alongside (or instead of) the defaults:
import { defaultSlashCommands, SlashCommand } from '@react-email/editor/ui';
import { ImageIcon } from 'lucide-react';
const customCommands = [
...defaultSlashCommands,
{
title: 'Image',
description: 'Insert an image',
searchTerms: ['photo', 'picture', 'img'],
icon: <ImageIcon size={18} />,
category: 'Media',
command: ({ editor, range }) => {
editor.chain().focus().deleteRange(range).setImage({ src: '' }).run();
},
},
];
<SlashCommand.Root items={customCommands} />
SlashCommandItem
interface SlashCommandItem {
title: string;
description: string;
searchTerms?: string[];
icon: ReactNode;
category: string;
command: (props: { editor: Editor; range: Range }) => void;
}
SlashCommandRenderProps
interface SlashCommandRenderProps {
items: SlashCommandItem[];
query: string;
selectedIndex: number;
onSelect: (index: number) => void;
}
Default commands
The defaultSlashCommands export includes these built-in commands:
| Command | Category | Description |
|---|
| Text | Basic | Plain text paragraph |
| Heading 1 | Headings | Level 1 heading |
| Heading 2 | Headings | Level 2 heading |
| Heading 3 | Headings | Level 3 heading |
| Numbered List | Lists | Ordered list |
| Bullet List | Lists | Unordered list |
| Quote | Basic | Block quote |
| Section | Layout | Content section |
| 2 Columns | Layout | Two-column layout |
| 3 Columns | Layout | Three-column layout |
| 4 Columns | Layout | Four-column layout |
| Divider | Basic | Horizontal rule |
| Code | Basic | Code block |
| Button | Basic | Email button |
CSS import
import '@react-email/editor/styles/slash-command.css';