Skip to content

Custom Content Block

This feature is available with the Plugin for Business plan and higher.

If you're on the Plugin for Startup or Plugin Expansion plan, consider upgrading to access this feature. For more details, visit our pricing page or contact support.

Custom blocks add your own entries to the editor's block sidebar, built either from the core block types or from raw HTML. They cover three common needs:

  • Embed custom HTML or functionality
    Add unique design elements or interactivity that are not available via standard blocks.

  • Align with your brand
    Create consistent components that match your company's design language and marketing standards.

  • Improve productivity
    Reuse common layouts or design sections without repetitive setup, which suits newsletters, headers and CTAs.

Only key and name are required on a custom block. Everything else is optional.

Creating a basic custom block

A custom block can be based on an existing core type: text, button, image or video. Define it in the customBlocks array inside TOPOL_OPTIONS and set type to the core block it builds on.

ts
customBlocks: [
{
  key: "custom-text-key", // unique ID
  name: "My Customised Text", // visible name in sidebar
  icon: `<svg style="width: 40px; height: 40px;" fill="currentColor" viewBox="0 0 20 20">...</svg>`, // SVG icon
  disabled: false,
  type: "text", // must match a valid Topol block type
  attributes: { // for more details, see INFO section below
    align: "right",
    padding: "10px 10px",
    "line-height": 1.3,
    "css-class": "hide_on_mobile"
  },
  content: "Custom Text block?"
}
]

INFO

Every attribute that exists on a block type can be defined here. The full list is in the block reference.

Attributes that fail the target block's schema are dropped silently rather than rejecting the block, so it is worth checking the reference above when an attribute does not take effect.

Choosing an icon

The icon property accepts three forms:

  • box or rss, the two built-in glyphs.
  • An inline SVG string, which has to start with <svg and end with </svg>. A fragment that fails either check falls back to the box glyph.
  • An https:// image URL, rendered as an image.

Composing multiple blocks

Several blocks can be combined into a single drag-and-drop unit with the mix type and a blocks array. The example below combines text and button, so dragging this custom block adds both elements at once. Inside blocks, type is required on every entry.

ts
customBlocks: [
{
  key: "custom-mix",
  name: "Custom mixed block",
  icon: "box",
  disabled: false,
  type: "mix",
  blocks: [
    {
      type: "text",
      attributes: {
        align: "left",
      },
      content: "My custom content",
    },
    {
      type: "button",
      attributes: { 
        align: "center",
        "background-color": "#417505",
        color: "#F8E71C",
      },
      content: "Click me!",
    },
  ],
},
]

Modifying and restricting attributes

Control and limit which settings can be changed by the user. In the example below, we disabled background color changing and set a default value for the block.

ts
customBlocks: [
{
  key: "custom-text-with-modifier",
  name: "My Customised Text",
  icon: "box",
  type: "button",
  attributes: {
    "font-size": "20px",
    "background-color": {
      value: "#417505",
      disabled: true,
    },
    href: {
      value: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    },
  },
  content: "Watch the video",
},
]

Marking a block as disabled or beta

disabled: true greys the block out, removes its drag handle and ignores clicks, which suits gating a block behind your own entitlement checks. disabledBadge sets the label shown on it, and beta adds a beta badge to a block that stays usable.

ts
customBlocks: [
{
  key: "custom-premium",
  name: "Premium layout",
  icon: "box",
  type: "text",
  disabled: true,
  disabledBadge: "Pro only",
  beta: false,
  content: "Upgrade to use this block",
},
]

Using custom HTML with a custom dialog

For complete control over the block's structure and interactivity, omit type entirely and set dialog: true. The block then carries raw HTML, edited through a dialog you provide.

WARNING

We want to clarify that we cannot assume responsibility for the content, security, or performance of custom HTML code that originates outside our official codebase. Users are advised to exercise caution and follow coding best practices when incorporating custom HTML, ensuring compliance with relevant standards and security measures.

ts
customBlocks: [
  {
    key: "custom-block-key",
    name: "My Custom Block", //displayed in menu
    dialog: true, //edit content in dialog (currently only custom dialog)
    icon: "box", // box and rss are built in, or pass an SVG string or an https:// image URL
    content: "<p>initial content</p>", // custom HTML code
    dialogButtonText: "Open Custom Dialog",
    disabled: false, //disabled button for certian users
  },
];

In the example above, we provided the text "Open Custom Dialog" for the button. When a user clicks the button, the onOpenCustomBlockDialog() callback is fired:

ts
callbacks: {
  onOpenCustomBlockDialog(customBlock) {
    // Open your custom dialog
    // Retreive edited data
    // Access current content via customBlock.content
    const editedContent = prompt("Edit HTML content:", customBlock.content);

    // Once the dialog is closed, we can update the current block using following function
    TopolPlugin.updateCustomBlockContent(editedContent);
  }
}

customBlock.content carries the content of the placed block as it currently stands, rather than the default from your configuration, so reopening the dialog gives back the user's latest edit.