Skip to main content
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.
char
string
default:"/"
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:
CommandCategoryDescription
TextBasicPlain text paragraph
Heading 1HeadingsLevel 1 heading
Heading 2HeadingsLevel 2 heading
Heading 3HeadingsLevel 3 heading
Numbered ListListsOrdered list
Bullet ListListsUnordered list
QuoteBasicBlock quote
SectionLayoutContent section
2 ColumnsLayoutTwo-column layout
3 ColumnsLayoutThree-column layout
4 ColumnsLayoutFour-column layout
DividerBasicHorizontal rule
CodeBasicCode block
ButtonBasicEmail button

CSS import

import '@react-email/editor/styles/slash-command.css';