Skip to content

Toolbar Layout Customization

The @lyfie/luthor package provides a flexible toolbar layout system that allows you to customize the grouping and ordering of toolbar buttons to match your preferred editing interface.

Luthor ships with two predefined toolbar layouts:

The TRADITIONAL_TOOLBAR_LAYOUT groups toolbar items in a familiar pattern similar to word processors like Microsoft Word or Google Docs:

  1. Typography Controls - Font family, font size, line height
  2. Text Formatting - Bold, italic, underline, strikethrough, text color, text highlight
  3. Enhanced Formatting - Subscript, superscript, inline code, link
  4. Paragraph & Alignment - Block format (headings/paragraph), quote, text alignment (left, center, right, justify)
  5. Lists - Bullet list, numbered list, checklist, indent, outdent
  6. Insert Elements - Table, image, emoji, embeds, horizontal rule
  7. Code Blocks - Code block toggle
  8. History - Undo, redo
  9. Utilities - Command palette, theme toggle

The DEFAULT_TOOLBAR_LAYOUT maintains the original grouping pattern for backward compatibility.

Pass the toolbarLayout prop to customize the toolbar:

import { ExtensiveEditor, TRADITIONAL_TOOLBAR_LAYOUT } from "@lyfie/luthor";
function MyEditor() {
return (
<ExtensiveEditor
placeholder="Start writing..."
toolbarLayout={TRADITIONAL_TOOLBAR_LAYOUT}
/>
);
}

The ExtensiveEditor uses TRADITIONAL_TOOLBAR_LAYOUT by default, so you only need to specify it if you want to override with a custom layout.

If you’re building a custom preset, you can pass the layout directly to the Toolbar component:

import { Toolbar, TRADITIONAL_TOOLBAR_LAYOUT } from "@lyfie/luthor/core";
function MyCustomEditor() {
return (
<Toolbar
commands={commands}
hasExtension={hasExtension}
activeStates={activeStates}
isDark={isDark}
toggleTheme={toggleTheme}
onCommandPaletteOpen={handleCommandPaletteOpen}
layout={TRADITIONAL_TOOLBAR_LAYOUT}
/>
);
}

You can create your own toolbar layout by defining a ToolbarLayout object:

import type { ToolbarLayout } from "@lyfie/luthor";
const myCustomLayout: ToolbarLayout = {
sections: [
{
// Group basic formatting together
items: ["bold", "italic", "underline", "strikethrough"],
},
{
// Typography controls
items: ["fontFamily", "fontSize", "textColor"],
},
{
// Block-level formatting
items: ["blockFormat", "alignLeft", "alignCenter", "alignRight"],
},
{
// Lists
items: ["unorderedList", "orderedList", "indentList", "outdentList"],
},
{
// Insert tools
items: ["link", "image", "table", "horizontalRule"],
},
{
// Utilities
items: ["undo", "redo", "commandPalette", "themeToggle"],
},
],
};

Then use it in your editor:

<ExtensiveEditor toolbarLayout={myCustomLayout} />

Here’s the complete list of toolbar items you can include in your custom layout:

  • fontFamily - Font family selector
  • fontSize - Font size selector
  • lineHeight - Line height selector
  • textColor - Text color picker
  • textHighlight - Text background highlight color picker
  • bold - Bold text
  • italic - Italic text
  • underline - Underline text
  • strikethrough - Strikethrough text
  • subscript - Subscript text
  • superscript - Superscript text
  • code - Inline code
  • link - Insert/remove link
  • blockFormat - Block type selector (paragraph, headings)
  • quote - Blockquote toggle
  • alignLeft - Align text left
  • alignCenter - Align text center
  • alignRight - Align text right
  • alignJustify - Justify text
  • codeBlock - Code block toggle
  • unorderedList - Bullet list
  • orderedList - Numbered list
  • checkList - Checklist
  • indentList - Indent list item
  • outdentList - Outdent list item
  • horizontalRule - Insert horizontal rule
  • table - Insert table
  • image - Insert image (with URL/file upload options)
  • emoji - Insert emoji
  • embed - Insert embed (iframe/YouTube)
  • undo - Undo last action
  • redo - Redo last undone action
  • commandPalette - Open command palette
  • themeToggle - Toggle light/dark theme
  • Items are automatically hidden if their corresponding extension is not loaded
  • Empty sections (sections with no visible items) are not rendered
  • The toolbar respects extension availability, so missing extensions won’t show buttons
  • Each section is visually separated with appropriate spacing

Here’s a minimal layout for a simple editor:

const minimalLayout: ToolbarLayout = {
sections: [
{
items: ["bold", "italic", "link"],
},
{
items: ["unorderedList", "orderedList"],
},
{
items: ["undo", "redo"],
},
],
};

A layout optimized for long-form writing:

const writerLayout: ToolbarLayout = {
sections: [
{
items: ["fontSize", "fontFamily"],
},
{
items: ["bold", "italic", "underline"],
},
{
items: ["blockFormat", "quote"],
},
{
items: ["alignLeft", "alignCenter", "alignJustify"],
},
{
items: ["link", "image", "horizontalRule"],
},
{
items: ["undo", "redo", "commandPalette"],
},
],
};