Ritext

SlashCommand

A slash-command menu that lets users insert blocks by typing / anywhere in the editor.

The SlashCommand component renders a floating command palette when the user types / at the start of an empty block. Select an item with the mouse or keyboard to insert content at that position.

Import

import { SlashCommand, SlashItems } from 'ritext';

Usage

Place SlashCommand anywhere inside <Editor>. It reads the editor context automatically — no extra props required for basic usage.

import { Editor, Toolbar, Content, SlashCommand } from 'ritext';
import { Bold, Heading, BulletList } from 'ritext/extension/...';

<Editor extensions={[Bold, Heading, BulletList, ...]}>
  <Toolbar />
  <Content />
  <SlashCommand />
</Editor>

Props

Prop

Type

SlashItems

SlashItems is a pre-built dictionary of ready-to-use command items. Each entry is a SlashCommandItem that you can include directly in the items prop.

KeyExtension requiredAction
SlashItems.Paragraphparagraph (built-in)Set block to paragraph
SlashItems.Heading1Heading6headingToggle heading level 1–6
SlashItems.BulletListbulletListToggle bullet list
SlashItems.OrderedListorderedListToggle ordered list
SlashItems.TaskListtaskListToggle task list
SlashItems.BlockQuoteblockquoteToggle blockquote
SlashItems.ImageimageOpen the Image dialog
SlashItems.TabletableInsert a 3 × 3 table
SlashItems.HorizontalRulehorizontalRuleInsert a horizontal rule

If an extension required by a SlashItem is not registered on your <Editor>, that item is automatically filtered out and a console.error is logged with instructions.

Grouping Items

Pass a plain string anywhere in the items array to start a new named group. Every item that follows belongs to that group until the next string.

import { SlashCommand, SlashItems } from 'ritext';

<SlashCommand
  items={[
    'Headings',
    SlashItems.Heading1,
    SlashItems.Heading2,
    SlashItems.Heading3,
    'Lists',
    SlashItems.BulletList,
    SlashItems.OrderedList,
  ]}
/>

Items added before the first string header are rendered without a label.

Custom Items

Build your own SlashCommandItem and mix it with built-in ones:

import { SlashCommand, SlashItems, type SlashCommandItem } from 'ritext';
import { CodeIcon } from 'lucide-react';

const CodeBlock: SlashCommandItem = {
  id: 'slash-code-block',
  icon: <CodeIcon size={14} />,
  title: 'Code Block',
  description: 'Insert a fenced code block',
  extensionName: 'codeBlock',         // optional — used for validation
  command: (editor) => editor.chain().focus().toggleCodeBlock().run(),
};

<SlashCommand
  items={[
    'Format',
    SlashItems.Paragraph,
    SlashItems.Heading1,
    SlashItems.Heading2,
    CodeBlock,
  ]}
/>

SlashCommandItem Type

type SlashCommandItem = {
  id: string;
  icon?: ReactNode;
  title: string;
  description?: string;
  /** Extension name used to validate the item is registered. Filtered out with a warning if missing. */
  extensionName?: string;
  command: (editor: Editor) => void;
  /** Optional sub-panel rendered instead of running command (e.g. ImageDialog). */
  panel?: (args: { editor: Editor; onClose: () => void }) => ReactNode;
  /** When true the panel manages its own UI (portal/dialog). No wrapper is rendered. */
  panelAsDialog?: boolean;
};

Keyboard Navigation

KeyAction
Move highlight down
Move highlight up
EnterExecute highlighted item
EscapeClose the menu

The highlighted item scrolls into view automatically when navigating with the keyboard.

Filtering

As the user types after /, the list is filtered in real time against item titles. Typing /he shows only Heading items; typing /bu shows BulletList, etc.

Positioning

SlashCommand uses @floating-ui/react with autoUpdate to anchor the dropdown to the cursor position. The panel repositions automatically on scroll and window resize — no manual listeners needed.

How It Works

  1. On every editor update and selectionUpdate, SlashCommand checks whether the text from the start of the current block to the cursor begins with / and contains no spaces.
  2. If it does, the dropdown opens at the cursor position.
  3. When an item is selected, the slash text is removed and the block is normalised to a clean top-level paragraph before the item command runs, ensuring consistent insertion regardless of whether the slash was typed inside a heading, list, or blockquote.

SlashCommand must be a child of <Editor>. It uses React context to access the editor instance.

On this page