ExamplesCustom SchemasCallout Block

Callout Block

In this example, we create a custom Callout block with a real rich-text title and child blocks inside it (a titled block), like a Notion-style callout.

The block has content: "inline": the title is ordinary inline content — formatting, links, and multiplayer cursors all work — and its child blocks live on block.children at runtime. Its keyboard settings keep the child blocks inside the callout: Enter in the title adds a first child block, Shift-Tab doesn't move child blocks out, and Enter in an empty last child block leaves the callout. render draws the title row and renderFrame draws the box around the title and child blocks together.

We also wire up a Slash Menu item to insert the callout.

Try it out:

  • Press Enter at the end of the callout's title to add a block inside the callout.
  • Press Enter in an empty last block inside the callout to leave the callout.
  • Press Backspace at the start of the first block inside the callout to merge it back into the title.
  • Press "/" inside the callout and add a code block, heading, or list.

Relevant Docs:

import { BlockNoteSchema } from "@blocknote/core";import {  filterSuggestionItems,  insertOrUpdateBlockForSlashMenu,} from "@blocknote/core/extensions";import "@blocknote/core/fonts/inter.css";import { BlockNoteView } from "@blocknote/mantine";import "@blocknote/mantine/style.css";import {  SuggestionMenuController,  getDefaultReactSlashMenuItems,  useCreateBlockNote,} from "@blocknote/react";import { RiChatQuoteLine } from "react-icons/ri";import { createCallout } from "./Callout";import "./styles.css";// Schema with the default blocks plus our custom Callout titled block.const schema = BlockNoteSchema.create().extend({  blockSpecs: {    callout: createCallout(),  },});// Slash menu item to insert a Callout.function insertCallout(editor: typeof schema.BlockNoteEditor) {  return {    title: "Callout",    subtext: "Titled container block that wraps other blocks",    onItemClick: () =>      insertOrUpdateBlockForSlashMenu(editor, {        type: "callout",      }),    aliases: ["callout", "container", "alert", "note", "tip", "info"],    group: "Basic blocks",    icon: <RiChatQuoteLine />,  };}export default function App() {  const editor = useCreateBlockNote({    schema,    initialContent: [      {        type: "paragraph",        content:          "Welcome! This demo shows a titled block: a rich-text title with child blocks inside it.",      },      {        type: "callout",        content: "A callout with a real title",        children: [          {            type: "paragraph",            content:              "The title is ordinary inline content: formatting, links, and multiplayer cursors all work.",          },          {            type: "paragraph",            content:              "Press Enter at the end of the title to add a block inside the callout, or Backspace at the start of the first block inside to merge it back.",          },        ],      },      {        type: "paragraph",        content: "Press '/' anywhere to insert a new Callout.",      },      {        type: "paragraph",      },    ],  });  return (    <BlockNoteView editor={editor} slashMenu={false}>      <SuggestionMenuController        triggerCharacter={"/"}        getItems={async (query) =>          filterSuggestionItems(            [...getDefaultReactSlashMenuItems(editor), insertCallout(editor)],            query,          )        }      />    </BlockNoteView>  );}