Skip to main content
Lumen Editor’s toolbar is driven by an array of module objects — each one describing a command that can appear as a button. You can define your own modules with exactly the same shape as the built-ins and slot them into any position in the toolbar. This lets you add new formatting commands, trigger custom actions, or integrate third-party functionality without touching the editor’s internals.

Module object shape

Every toolbar button corresponds to a module object with five fields:
FieldTypeDescription
namestringUnique identifier for the command, used to reference it in the toolbar config.
groupstringLogical grouping: 'inline', 'block', 'history', 'insert', or any custom string. Used for styling and separator logic.
iconstringHTML string rendered inside the toolbar button — can be an emoji, a Unicode character, or an inline SVG.
labelstringTooltip text shown on hover. Also used as the accessible label for the button.
exec(editor: Editor) => voidFunction called when the button is clicked. Receives the editor instance.
The icon field is rendered as raw HTML inside the button element, so you can pass a full <svg>...</svg> string for crisp, scalable icons at any size — not just emoji or text characters.

Writing a custom module

Define a module object that follows the shape above. The example below adds a highlight command that applies a yellow background to the selected text:
const highlight = {
  name: 'highlight',
  group: 'inline',
  icon: '★',
  label: 'highlight',
  exec: (editor) => document.execCommand('hiliteColor', false, 'yellow')
};
The exec function receives the live editor instance, so you can call any public editor method, read the current selection, or dispatch DOM commands just like the built-in modules do.

Merging with built-in modules

Lumen Editor exports a modules object whose values are all the built-in module definitions. Spread them alongside your custom module so the editor retains its default commands:
import { Editor, modules } from 'lumen-editor';

const highlight = {
  name: 'highlight',
  group: 'inline',
  icon: '★',
  label: 'highlight',
  exec: (editor) => document.execCommand('hiliteColor', false, 'yellow')
};

// Built-ins first, then your custom module(s)
const allModules = [...Object.values(modules), highlight];
This pattern preserves every built-in command while making highlight available for use in the toolbar config.

Adding to the toolbar config

The toolbar option is an array of groups, where each group is an array of command name strings. Add your module’s name to whichever group makes the most sense:
new Editor('#e', {
  modules: allModules,
  toolbar: [
    ['bold', 'italic', 'underline', 'highlight'],  // inline group
    ['bulletList', 'orderedList', 'blockquote'],    // block group
    ['undo', 'redo']                                // history group
  ]
});
Buttons are rendered in the order you list them within each group. Groups are separated by visual dividers in the toolbar.

Full combined example

import { Editor, modules } from 'lumen-editor';

const highlight = {
  name: 'highlight',
  group: 'inline',
  icon: '★',
  label: 'highlight',
  exec: (editor) => document.execCommand('hiliteColor', false, 'yellow')
};

const editor = new Editor('#e', {
  modules: [...Object.values(modules), highlight],
  toolbar: [
    ['bold', 'italic', 'highlight'],
    ['bulletList', 'orderedList'],
    ['undo', 'redo']
  ]
});
You can register multiple custom modules at once by appending them all to the spread: [...Object.values(modules), highlight, strikeColor, clearFormat]. As long as each module has a unique name, they can all coexist in the same editor instance.