Extend the Editor Toolbar

In this tutorial, you’ll learn how to extend the SmallBlock CMS editor toolbar by adding a custom button. Toolbar extensions allow developers to introduce editor-facing tools — such as inserting snippets, shortcodes, or formatted text — without altering the CMS core.

You will create a simple “Insert Quote” button that adds a canned sentence wherever the editor’s cursor is located.

Before You Begin

You should have:

This tutorial assumes the plugin you created earlier is located in:

plugins/quote_of_the_day/

How Toolbar Extensions Work

SmallBlock exposes a global JavaScript interface named SmallBlock.Toolbar that allows plugins to register new buttons.

A toolbar extension includes:

  • A JavaScript file containing registration code

  • (Optional) a stylesheet to customize button appearance

  • A registration entry in plugin.py

The diagram below illustrates the client-side extension flow:

digraph G {
    rankdir=LR;
    node [shape=box, style="rounded,filled", fillcolor="#eef3f8"];

    A [label="Static JS File\n(toolbar-quote.js)"];
    B [label="SmallBlock.Toolbar.registerButton()"];
    C [label="CMS Editor UI"];
    D [label="User Clicks Button"];
    E [label="Editor Inserts Text"];

    A -> B -> C -> D -> E;
}

Step 1 — Create a Static Asset Directory

Inside your plugin folder, create directories for JavaScript and CSS assets:

cd mysite/plugins/quote_of_the_day
mkdir -p static/js
mkdir -p static/css

Verify

Your plugin directory should now contain:

quote_of_the_day/
├── plugin.py
├── __init__.py
└── static/
    ├── js/
    └── css/

Step 2 — Add the JavaScript Toolbar Extension

Create static/js/toolbar-quote.js:

(function () {
  // Wait for the CMS runtime
  if (!window.SmallBlock || !SmallBlock.Toolbar) {
    console.warn("SmallBlock.Toolbar not available.");
    return;
  }

  SmallBlock.Toolbar.registerButton({
    id: "insert-quote",
    label: "Insert Quote",
    icon: "💬",
    tooltip: "Insert Quote of the Day",
    onClick: function (editor) {
      const quote =
        "“The only way to do great work is to love what you do.” — Steve Jobs";
      editor.insertText(quote);
    },
  });

  console.log("Toolbar extension: Insert Quote loaded.");
})();

Explanation

  • registerButton() adds a button to the editor toolbar.

  • editor.insertText() inserts content at the user’s cursor.

Verify

Check the browser console while loading the editor UI:

You should see:

Toolbar extension: Insert Quote loaded.

Step 3 — Register the Static Files

Add the JS file to your plugin registration in plugin.py:

def register(app):
    app.add_static("quote_of_the_day/js/toolbar-quote.js")
    app.logger.info("Toolbar extension registered.")

Restart the development server:

smallblock runserver

Verify

Open your browser’s developer tools → Network tab. You should see the file:

/static/quote_of_the_day/js/toolbar-quote.js

Step 4 — Add Optional Styling

Create static/css/toolbar-quote.css:

.sb-toolbar-button#insert-quote {
    background-color: #16364b;
    color: #e6edf3;
    border-radius: 6px;
    padding: 0.25rem 0.5rem;
    transition: background-color 0.2s ease-in-out;
}

.sb-toolbar-button#insert-quote:hover {
    background-color: #23445a;
}

Then update your plugin registration:

def register(app):
    app.add_static("quote_of_the_day/js/toolbar-quote.js")
    app.add_static("quote_of_the_day/css/toolbar-quote.css")
    app.logger.info("Toolbar extension registered.")

Step 5 — Use the Toolbar Button

To verify your button is working:

  1. Open any page in the SmallBlock editor UI.

  2. Look for the new 💬 Insert Quote button.

  3. Place the cursor within the editor.

  4. Click the button.

Result A predefined quote should appear at the cursor location.

Troubleshooting

The button doesn’t appear

  • Ensure the JS file is being loaded:

    curl -I http://127.0.0.1:8000/static/quote_of_the_day/js/toolbar-quote.js
    
  • Confirm the plugin is enabled in your configuration.

  • Check the browser console for JavaScript errors.

Button appears, but clicking does nothing

  • The editor instance may not be available; check for errors in:

    SmallBlock.Toolbar.registerButton

Styles not applying

  • Make sure the CSS file path is correct.

  • Inspect the element — another rule may be overriding your styles.

Next Steps

Continue building interactive and dynamic features with: