Editor Menus in React Block Editor component
29 Aug 202524 minutes to read
The Block Editor component includes several intuitive, context-aware menus that streamline content creation and editing. These menus provide quick access to formatting options and commands, improving user productivity.
Slash command menu
The Slash Command menu allows users to quickly insert or transform blocks by typing /
followed by a command. This provides an efficient, keyboard-driven way to interact with the editor.
Built-in items
The Slash Command menu comes with a set of pre-defined commands for all block types:
- Headings (Level 1 to 4): Inserts a heading block of the corresponding level.
- Lists (Bullet, Numbered, Checklist): Creates a block for the specified list type.
- Paragraph: Inserts a standard text block.
- Image: Inserts a media block for images.
- Toggle: Creates a collapsible content block.
- Callout: Inserts a block for highlighting important information.
- Utility (Divider, Quote, Code): Inserts a utility block like a divider, quote, or code block.
Customize Slash command menu
You can use the commandMenu property to modify the Slash Command menu. This allows you to add custom commands, remove default items, or change the behavior of existing commands to fit your application’s requirements.
Show or hide tooltip
By default, a tooltip is displayed when the user hovers over a command item. You can show or hide the tooltip using the enableTooltip property on the command menu settings.
Events
The following events are available for the Slash Command menu:
Name | Args | Description |
---|---|---|
open | CommandMenuOpenEventArgs | Triggers when the command menu is opened. |
close | CommandMenuCloseEventArgs | Triggers when the command menu is closed. |
queryFiltering | CommandQueryFilteringEventArgs | Triggers when the user types to filter the command menu items. |
itemClicked | CommandItemClickedEventArgs | Triggers when the user clicks on a command menu item. |
The following example demonstrates how to customize the Slash Command menu.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent } from '@syncfusion/ej2-react-blockeditor';
const blocksData = [
{
id: 'demo-block',
type: 'Paragraph',
content: [
{
type: 'Text',
content: 'Type "/" anywhere in this editor to open the custom slash command menu.'
}
]
}
];
const commandItems = [
{
id: 'line-cmd',
type: 'Divider',
groupHeader: 'Utility',
label: 'Insert a Line',
iconCss: 'e-icons e-divider',
},
{
id: 'timestamp-cmd',
groupHeader: 'Actions',
label: 'Insert Timestamp',
iconCss: 'e-icons e-schedule',
}
];
function App() {
const handleItemClicked = (args) => {
// Handle custom command actions
console.log('Command clicked:', args.item); // Debug
};
const handleOpen = (args) => {
// Your actions here
console.log('Command menu opened:', args); // Debug
};
const handleClose = (args) => {
// Your actions here
console.log('Command menu closed:', args); // Debug
};
const handleQueryFiltering = (args) => {
// Your actions here
console.log('Query filtering:', args); // Debug
};
return (
<div>
<div id="controls">
<h3>Slash Command Menu Configuration Demo</h3>
<div class="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>
Click in the editor below and type "/" to open the slash command
menu
</li>
<li>Notice the custom popup size, commands and disabled tooltips</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
commandMenu={{
popupWidth: '350px',
popupHeight: '400px',
enableTooltip: false,
commands: commandItems,
itemClicked: handleItemClicked,
open: handleOpen,
close: handleClose,
queryFiltering: handleQueryFiltering
}}
></BlockEditorComponent>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent, BlockModel, ContentType, CommandItemModel, CommandMenuOpenEventArgs, CommandMenuCloseEventArgs, CommandQueryFilteringEventArgs, CommandItemClickedEventArgs } from '@syncfusion/ej2-react-blockeditor';
const commandItems: CommandItemModel[] = [
{
id: 'line-cmd',
type: 'Divider',
groupHeader: 'Utility',
label: 'Insert a Line',
iconCss: 'e-icons e-divider',
},
{
id: 'timestamp-cmd',
groupHeader: 'Actions',
label: 'Insert Timestamp',
iconCss: 'e-icons e-schedule',
}
];
const blocksData: BlockModel[] = [
{
id: 'demo-block',
type: 'Paragraph',
content: [
{
type: ContentType.Text,
content: 'Type "/" anywhere in this editor to open the custom slash command menu.'
}
]
}
];
function App() {
const handleItemClicked = (args: CommandItemClickedEventArgs) => {
// Handle custom command actions
console.log('Command clicked:', args.item); // Debug
};
const handleOpen = (args: CommandMenuOpenEventArgs) => {
// Your actions here
console.log('Command menu opened:', args); // Debug
};
const handleClose = (args: CommandMenuCloseEventArgs) => {
// Your actions here
console.log('Command menu closed:', args); // Debug
};
const handleQueryFiltering = (args: CommandQueryFilteringEventArgs) => {
// Your actions here
console.log('Query filtering:', args); // Debug
};
return (
<div>
<div id="controls">
<h3>Slash Command Menu Configuration Demo</h3>
<div class="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>
Click in the editor below and type "/" to open the slash command
menu
</li>
<li>Notice the custom popup size, commands and disabled tooltips</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
created={() => console.log('BlockEditor initialized')} // Debug initialization
commandMenu={{
popupWidth: '350px',
popupHeight: '400px',
enableTooltip: false,
commands: commandItems,
itemClicked: handleItemClicked,
open: handleOpen,
close: handleClose,
queryFiltering: handleQueryFiltering
}}
style={{ border: '1px solid red' }} // Temporary styling to confirm rendering
></BlockEditorComponent>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));
Context menu
The Context menu appears when a user right-clicks within a specific block. It provides context-aware actions relevant to the clicked block or content.
Built-in items
The Context menu offers the following built-in options:
- Undo/Redo: Reverses or re-applies the last action.
- Cut/Copy/Paste: Standard clipboard actions for selected content.
- Indent: Increases or decreases the indent level of the selected block.
- Link: Adds or edits a hyperlink for the selected text.
Customize Context menu
You can use the contextMenu property to customize the Context menu. This allows you to add specific actions or modify existing items based on your application needs.
Events
The following events are available for the Context menu:
Name | Args | Description |
---|---|---|
beforeOpen | ContextMenuBeforeOpenEventArgs | Triggers before the context menu opens. |
open | ContextMenuOpenEventArgs | Triggers when the context menu is opened. |
beforeClose | ContextMenuBeforeCloseEventArgs | Triggers before the context menu closes. |
close | ContextMenuCloseEventArgs | Triggers when the context menu is closed. |
itemClick | ContextMenuItemClickEventArgs | Triggers when a context menu item is clicked. |
The following example demonstrates how to customize the Context menu.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent } from '@syncfusion/ej2-react-blockeditor';
function App() {
const customContextMenuItems = [
{
id: 'format-menu',
text: 'Format',
iconCss: 'e-icons e-format-painter',
items: [
{
id: 'bold-item',
text: 'Bold',
iconCss: 'e-icons e-bold',
},
{
id: 'italic-item',
text: 'Italic',
iconCss: 'e-icons e-italic',
},
{
id: 'underline-item',
text: 'Underline',
iconCss: 'e-icons e-underline',
}
]
},
{ separator: true },
{
id: 'statistics-item',
text: 'Block Statistics',
iconCss: 'e-icons e-chart'
},
{
id: 'export-item',
text: 'Export Options',
iconCss: 'e-icons e-export',
items: [
{
id: 'export-json',
text: 'Export as JSON',
iconCss: 'e-icons e-file-json'
},
{
id: 'export-html',
text: 'Export as HTML',
iconCss: 'e-icons e-file-html'
},
{
id: 'export-pdf',
text: 'Export as PDF',
iconCss: 'e-icons e-file-pdf'
}
]
}
];
const blocksData = [
{
id: 'title-block',
type: 'Heading',
props: { level: 1 },
content: [
{
type: 'Text',
content: 'Context Menu Demo'
}
]
},
{
id: 'intro-block',
type: 'Quote',
content: [
{
type: 'Text',
content: 'Right-click anywhere in this editor to open the custom context menu. Try different areas and blocks.'
}
]
}
];
const handleBeforeOpen = (args) => {
// Your actions here
};
const handleOpen = (args) => {
// Your actions here
};
const handleBeforeClose = (args) => {
// Your actions here
};
const handleClose = (args) => {
// Your actions here
};
const handleItemClick = (args) => {
// Handle custom actions here
};
return (
<div>
<div id="controls">
<h3>Context Menu Configuration Demo</h3>
<div class="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>Right-click anywhere in the editor to open the context menu</li>
<li>Notice the custom popup size, menu items and disabled tooltips</li>
<li>Try clicking on items with submenus (they appear on click, not hover)</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
contextMenu={{
enable: true,
showItemOnClick: true,
items: customContextMenuItems,
beforeOpen: handleBeforeOpen,
open: handleOpen,
beforeClose: handleBeforeClose,
close: handleClose,
itemClick: handleItemClick
}}
></BlockEditorComponent>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent, BlockModel, ContentType, ContextMenuBeforeOpenEventArgs, ContextMenuOpenEventArgs, ContextMenuBeforeCloseEventArgs, ContextMenuCloseEventArgs, ContextMenuItemClickEventArgs, ContextMenuItemModel } from '@syncfusion/ej2-react-blockeditor';
function App() {
const customContextMenuItems: ContextMenuItemModel[] = [
{
id: 'format-menu',
text: 'Format',
iconCss: 'e-icons e-format-painter',
items: [
{
id: 'bold-item',
text: 'Bold',
iconCss: 'e-icons e-bold',
},
{
id: 'italic-item',
text: 'Italic',
iconCss: 'e-icons e-italic',
},
{
id: 'underline-item',
text: 'Underline',
iconCss: 'e-icons e-underline',
}
]
},
{ separator: true },
{
id: 'statistics-item',
text: 'Block Statistics',
iconCss: 'e-icons e-chart'
},
{
id: 'export-item',
text: 'Export Options',
iconCss: 'e-icons e-export',
items: [
{
id: 'export-json',
text: 'Export as JSON',
iconCss: 'e-icons e-file-json'
},
{
id: 'export-html',
text: 'Export as HTML',
iconCss: 'e-icons e-file-html'
},
{
id: 'export-pdf',
text: 'Export as PDF',
iconCss: 'e-icons e-file-pdf'
}
]
}
];
const blocksData: BlockModel[] = [
{
id: 'title-block',
type: 'Heading',
props: { level: 1 },
content: [
{
type: ContentType.Text,
content: 'Context Menu Demo'
}
]
},
{
id: 'intro-block',
type: 'Quote',
content: [
{
type: ContentType.Text,
content: 'Right-click anywhere in this editor to open the custom context menu. Try different areas and blocks.'
}
]
}
];
const handleBeforeOpen = (args: ContextMenuBeforeOpenEventArgs) => {
// Your actions here
};
const handleOpen = (args: ContextMenuOpenEventArgs) => {
// Your actions here
};
const handleBeforeClose = (args: ContextMenuBeforeCloseEventArgs) => {
// Your actions here
};
const handleClose = (args: ContextMenuCloseEventArgs) => {
// Your actions here
};
const handleItemClick = (args: ContextMenuItemClickEventArgs) => {
// Handle custom actions here
};
return (
<div>
<div id="controls">
<h3>Context Menu Configuration Demo</h3>
<div class="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>Right-click anywhere in the editor to open the context menu</li>
<li>Notice the custom popup size, menu items and disabled tooltips</li>
<li>Try clicking on items with submenus (they appear on click, not hover)</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
contextMenu={{
enable: true,
showItemOnClick: true,
items: customContextMenuItems,
beforeOpen: handleBeforeOpen,
open: handleOpen,
beforeClose: handleBeforeClose,
close: handleClose,
itemClick: handleItemClick
}}
></BlockEditorComponent>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));
Block action menu
The Block Action menu appears next to a block when you hover over it and click the drag handle icon, offering quick actions specific to that block.
Built-in items
The Block Action menu provides convenient actions for managing individual blocks:
- Duplicate: Creates an exact copy of the current block.
- Delete: Removes the block from the editor.
- Move Up: Moves the block one position higher.
- Move Down: Moves the block one position lower.
Customize Block action menu
You can use the blockActionsMenu property to customize the Block action menu. This enables you to add block-specific commands that are relevant to your application, allowing for a highly tailored user experience.
Below example demonstrates how to customize the Block action menu.
Show or hide tooltip
By default, a tooltip is displayed when the user hovers over an action item. You can show or hide the tooltip using the enableTooltip property in the block action menu settings.
Events
The following events are available for the Block action menu:
Name | Args | Description |
---|---|---|
open | BlockActionMenuOpenEventArgs | Triggers when the block action menu is opened. |
close | BlockActionMenuCloseEventArgs | Triggers when the block action menu is closed. |
itemClick | BlockActionMenuItemClickEventArgs | Triggers when a block action menu item is clicked. |
The following example demonstrates how to customize the Block action menu.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent, BlockModel, ContentType } from '@syncfusion/ej2-react-blockeditor';
function App() {
const blocksData = [
{
id: 'title-block',
type: 'Heading',
props: { level: 1 },
content: [
{
type: ContentType.Text,
content: 'Block Action Menu Demo'
}
]
},
{
id: 'intro-block',
type: 'Quote',
content: [
{
type: ContentType.Text,
content: 'Hover over any block and click the drag handle icon to see custom actions.'
}
]
}
];
const handleMenuOpen = (args) => {
// Your actions here
};
const handleMenuClose = (args) => {
// Your actions here
};
const handleItemClick = (args) => {
// Handle custom block actions
};
return (
<div>
<div id="controls">
<h3>Block Action Menu Configuration Demo</h3>
<div className="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>Hover over any block in the editor to see the block action menu</li>
<li>Click on the action menu icon (⋮) next to any block</li>
<li>Notice the custom popup size, action items and disabled tooltips</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
blockActionsMenu={{
enable: true,
popupWidth: '180px',
popupHeight: '110px',
enableTooltip: false,
items: [
{
id: 'highlight-action',
label: 'Highlight Block',
iconCss: 'e-icons e-highlight',
tooltip: 'Highlight this block'
},
{
id: 'copy-content-action',
label: 'Copy Content',
iconCss: 'e-icons e-copy',
tooltip: 'Copy block content to clipboard'
},
{
id: 'block-info-action',
label: 'Block Info',
tooltip: 'Show block information'
}
],
open: handleMenuOpen,
close: handleMenuClose,
itemClick: handleItemClick
}}
/>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent, BlockModel, ContentType, BlockActionMenuOpenEventArgs, BlockActionMenuCloseEventArgs, BlockActionItemClickEventArgs} from '@syncfusion/ej2-react-blockeditor';
function App() {
const blocksData: BlockModel[] = [
{
id: 'title-block',
type: 'Heading',
props: { level: 1 },
content: [
{
type: ContentType.Text,
content: 'Block Action Menu Demo'
}
]
},
{
id: 'intro-block',
type: 'Quote',
content: [
{
type: ContentType.Text,
content: 'Hover over any block and click the drag handle icon to see custom actions.'
}
]
}
];
const handleMenuOpen = (args: BlockActionMenuOpenEventArgs) => {
console.log('Menu opened for block:', args.blockId);
};
const handleMenuClose = (args: BlockActionMenuCloseEventArgs) => {
console.log('Menu closed for block:', args.blockId);
};
const handleItemClick = (args: BlockActionItemClickEventArgs) => {
console.log('Action clicked:', args.item.id, 'on block:', args.blockId);
// You can add custom logic here for each action
};
return (
<div>
<div id="controls">
<h3>Block Action Menu Configuration Demo</h3>
<div className="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>Hover over any block in the editor to see the block action menu</li>
<li>Click on the action menu icon (⋮) next to any block</li>
<li>Notice the custom popup size, action items and disabled tooltips</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
blockActionsMenu={{
enable: true,
popupWidth: '180px',
popupHeight: '110px',
enableTooltip: false,
items: [
{
id: 'highlight-action',
label: 'Highlight Block',
iconCss: 'e-icons e-highlight',
tooltip: 'Highlight this block'
},
{
id: 'copy-content-action',
label: 'Copy Content',
iconCss: 'e-icons e-copy',
tooltip: 'Copy block content to clipboard'
},
{
id: 'block-info-action',
label: 'Block Info',
tooltip: 'Show block information'
}
],
open: handleMenuOpen,
close: handleMenuClose,
itemClick: handleItemClick
}}
/>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));
Inline Toolbar
The Inline Toolbar appears when text is selected in the editor, providing quick access to common text formatting actions that apply to inline content.
Built-in items
The Inline Toolbar includes the following built-in formatting options:
- Text Styles: Bold, Italic, Underline, and Strikethrough.
- Superscript/Subscript: For mathematical or scientific notations.
- Case Conversion: Change text to uppercase or lowercase.
- Text Color: Change the color of the selected text.
- Background Color: Change the background color of the selected text.
Customize Inline Toolbar
You can use the inlineToolbar property to customize the Inline Toolbar by adding or removing formatting options based on your application’s needs.
Below example demonstrates how to customize the Inline Toolbar.
Show or hide tooltip
By default, a tooltip is displayed when the user hovers over a toolbar item. You can show or hide this tooltip using the enableTooltip property in the inline toolbar settings.
Events
The following events are available for the Inline Toolbar:
Name | Args | Description |
---|---|---|
open | ToolbarOpenEventArgs | Triggers when the inline toolbar is opened. |
close | ToolbarCloseEventArgs | Triggers when the inline toolbar is closed. |
itemClicked | ToolbarItemClickedEventArgs | Triggers when the user clicks on an inline toolbar item. |
The following example demonstrates how to customize the Inline Toolbar.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent } from '@syncfusion/ej2-react-blockeditor';
function App() {
const customToolbarItems = [
{ id: 'clear', iconCss: 'e-icons e-format-painter', item: 'Custom', tooltip: 'Format Painter' },
{ id: 'highlight', iconCss: 'e-icons e-highlight', item: 'Custom', tooltip: 'Highlight' },
];
const blocksData = [
{
id: 'title-block',
type: 'Heading',
props: { level: 1 },
content: [
{
type: 'Text',
content: 'Inline Toolbar Demo'
}
]
},
{
id: 'intro-block',
type: 'Quote',
content: [
{
type: 'Text',
content: 'Select any text in the editor to open the Inline Toolbar'
}
]
}
];
const handleOpen = (args) => {
// Your actions here
};
const handleClose = (args) => {
// Your actions here
};
const handleItemClicked = (args) => {
// Handle custom actions here
};
return (
<div>
<div id="controls">
<h3>Inline Toolbar Configuration Demo</h3>
<div class="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>Select any text in the editor to open the Inline Toolbar</li>
<li>Notice the custom popup size, toolbar items and enabled tooltips</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
inlineToolbar={{
width: '80px',
enable: true,
items: customToolbarItems,
enableTooltip: true,
open: handleOpen,
close: handleClose,
itemClicked: handleItemClicked
}}
></BlockEditorComponent>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BlockEditorComponent, BlockModel, ContentType, ToolbarItemModel, ToolbarOpenEventArgs, ToolbarCloseEventArgs, ToolbarItemClickedEventArgs } from '@syncfusion/ej2-react-blockeditor';
function App() {
const customToolbarItems: ToolbarItemModel[] = [
{ id: 'clear', iconCss: 'e-icons e-format-painter', item: 'Custom', tooltip: 'Format Painter' },
{ id: 'highlight', iconCss: 'e-icons e-highlight', item: 'Custom', tooltip: 'Highlight' },
];
const blocksData: BlockModel[] = [
{
id: 'title-block',
type: 'Heading',
props: { level: 1 },
content: [
{
type: ContentType.Text,
content: 'Inline Toolbar Demo'
}
]
},
{
id: 'intro-block',
type: 'Quote',
content: [
{
type: ContentType.Text,
content: 'Select any text in the editor to open the Inline Toolbar'
}
]
}
];
const handleOpen = (args: ToolbarOpenEventArgs) => {
// Your actions here
};
const handleClose = (args: ToolbarCloseEventArgs) => {
// Your actions here
};
const handleItemClicked = (args: ToolbarItemClickedEventArgs) => {
// Handle custom actions here
};
return (
<div>
<div id="controls">
<h3>Inline Toolbar Configuration Demo</h3>
<div class="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>Select any text in the editor to open the Inline Toolbar</li>
<li>Notice the custom popup size, toolbar items and enabled tooltips</li>
</ol>
</div>
</div>
<BlockEditorComponent
id="blockeditor"
blocks={blocksData}
inlineToolbar={{
width: '80px',
enable: true,
items: customToolbarItems,
enableTooltip: true,
open: handleOpen,
close: handleClose,
itemClicked: handleItemClicked
}}
></BlockEditorComponent>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('container'));