JSFiddle - React, Tailwind, and code Playground
by Froala_marketing
June 29, 2026
HTML
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/froala-editor@5/css/froala_editor.pkgd.min.css" />
<div id="editor-container">
<div id="froala-editor">
<p>Type <strong>/</strong> at the start of a new line to open the command menu.</p>
</div>
</div>
<!-- The slash command dropdown -->
<div id="slash-menu"></div>
<script src="https://cdn.jsdelivr.net/npm/froala-editor@5/js/froala_editor.pkgd.min.js"></script>
CSS
/* ─── Slash Command Menu Styles ─────────────────────────────── */
#slash-menu {
position: absolute;
z-index: 9999;
background: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
width: 260px;
max-height: 320px;
overflow-y: auto;
display: none; /* Hidden by default */
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
#slash-menu .slash-menu-header {
padding: 8px 12px 4px;
font-size: 11px;
font-weight: 600;
color: #94a3b8;
text-transform: uppercase;
letter-spacing: 0.06em;
}
#slash-menu .slash-menu-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
cursor: pointer;
transition: background 0.1s ease;
}
#slash-menu .slash-menu-item:hover,
#slash-menu .slash-menu-item.is-active {
background: #f1f5f9;
}
#slash-menu .slash-menu-item .item-icon {
width: 32px;
height: 32px;
border-radius: 6px;
background: #f8fafc;
border: 1px solid #e2e8f0;
display: flex;
align-items: center;
justify-content: center;
font-size: 15px;
flex-shrink: 0;
}
#slash-menu .slash-menu-item .item-text .item-title {
font-size: 13px;
font-weight: 500;
color: #1e293b;
line-height: 1.3;
}
#slash-menu .slash-menu-item .item-text .item-description {
font-size: 11px;
color: #94a3b8;
line-height: 1.3;
}
/* Editor wrapper */
#editor-container {
max-width: 800px;
margin: 40px auto;
padding: 0 20px;
}
JavaScript
(function () {
'use strict';
// ─── 1. Define the menu items ──────────────────────────────────────────────
// Each item has: a label, description, icon, category, and an `action`
// function that receives the editor instance and performs the insertion.
const SLASH_COMMANDS = [
{
category: 'Text',
items: [
{
id: 'paragraph',
title: 'Text',
description: 'Plain paragraph',
icon: '¶',
action: function (editor) {
// Insert a plain paragraph and place cursor inside it
editor.html.insert('<p></p>'); // zero-width space keeps the <p> alive
}
},
{
id: 'h1',
title: 'Heading 1',
description: 'Large section heading',
icon: 'H1',
action: function (editor) {
editor.html.insert('<h1></h1>');
}
},
{
id: 'h2',
title: 'Heading 2',
description: 'Medium section heading',
icon: 'H2',
action: function (editor) {
editor.html.insert('<h2></h2>');
}
},
{
id: 'h3',
title: 'Heading 3',
description: 'Small section heading',
icon: 'H3',
action: function (editor) {
editor.html.insert('<h3></h3>');
}
},
]
},
{
category: 'Lists',
items: [
{
id: 'ul',
title: 'Bullet List',
description: 'Unordered list',
icon: '•',
action: function (editor) {
editor.html.insert('<ul><li></li></ul>');
}
},
{
id: 'ol',
title: 'Numbered List',
description: 'Ordered list',
icon: '1.',
action: function (editor) {
editor.html.insert('<ol><li></li></ol>');
}
},
...