Block Based
GitHub

Customization

The editor can be extended with custom blocks, sidebar tabs, templates, and feature flags — including customizing the main sidebar tab bar.

Sample Blocks

Add custom blocks to the sidebar's Content tab. Each sample block has a label, optional description and icon, and a factory function that produces a block:

import { EmailBlockEditor } from 'block-based';
import type { SampleBlock, EmailBlock } from 'block-based';

const sampleBlocks: SampleBlock[] = [
  {
    label: 'Brand Header',
    description: 'Company logo and tagline',
    icon: '🏢',
    create: (): EmailBlock => ({
      id: crypto.randomUUID(),
      type: 'html',
      content: '<div style="text-align:center"><h1>Acme Inc.</h1></div>',
      paddingTop: 16,
      paddingBottom: 16,
      paddingLeft: 0,
      paddingRight: 0,
      marginTop: 0,
      marginBottom: 0,
      marginLeft: 0,
      marginRight: 0,
      borderTopWidth: 0,
      borderBottomWidth: 0,
      borderLeftWidth: 0,
      borderRightWidth: 0,
      borderColor: '',
      borderStyle: 'solid',
      opacity: 100,
    }),
  },
];

<EmailBlockEditor sampleBlocks={sampleBlocks} />

Custom Sidebar Tabs

Add entirely new tabs to the sidebar. Custom tabs are rendered after any built-in tabs that remain enabled, so you can tailor the main tab bar to your app:

import { Settings2 } from 'lucide-react';
import type { CustomTab } from 'block-based';

const tabs: CustomTab[] = [
  {
    id: 'branding',
    label: 'Branding',
    icon: Settings2,
    render: (ctx) => (
      <div>
        <p>Document has {ctx.doc.sections.length} sections</p>
        <button onClick={() => ctx.updateSettings({ fontFamily: 'Georgia, serif' })}>
          Use serif font
        </button>
      </div>
    ),
  },
];

<EmailBlockEditor
  features={{ json: false, html: false }}
  customTabs={tabs}
/>

The CustomTabContext provides:

FieldTypeDescription
docEmailDocumentCurrent document state
selectionSelection | nullThe currently selected block or section
updateSettings(patch: Partial&lt;EmailDocumentSettings&gt;) => voidUpdate global document settings

Section Templates

Provide pre-built section templates that appear in the Templates sidebar tab:

import type { TemplateDefinition, EmailSectionInput } from 'block-based';

const templates: TemplateDefinition[] = [
  {
    label: 'Newsletter Header',
    description: 'Logo + navigation menu',
    sections: [
      {
        columns: [
          {
            width: '100%',
            blocks: [
              { type: 'image', src: '/logo.png', alt: 'Logo', width: '120px' },
              { type: 'menu', items: [
                { label: 'Home', url: '#' },
                { label: 'Blog', url: '#' },
              ]},
            ],
          },
        ],
      },
    ],
  },
];

<EmailBlockEditor templates={templates} />

Feature Flags

Toggle UI features on or off:

<EmailBlockEditor
  features={{
    content: true,       // Block palette sidebar tab
    rows: true,          // Layout presets sidebar tab
    templates: false,    // Hide templates tab
    treeView: false,     // Hide document tree
    json: false,         // Hide the built-in JSON tab
    html: false,         // Hide the built-in HTML tab
    bodySettings: true,  // Global settings panel
    preview: true,       // HTML preview
    dragDrop: true,      // Drag-and-drop
    customColors: true,  // Custom colors in palette
  }}
/>

All flags default to true. Set any of them to false to hide that part of the UI.