🚀 BlockNote AI is here! Access the early preview.
BlockNote Docs/Features/Custom Schemas/Custom Inline Content

Custom Inline Content Types

In addition to the default inline content types that BlockNote offers, you can also make your own custom inline content using React components. Take a look at the demo below, in which we add a custom mention tag to a BlockNote editor, as well as a custom Suggestion Menu to insert it.

Creating a Custom Inline Content Type

Use the createReactInlineContentSpec function to create a custom inline content type. This function takes two arguments:

function createReactInlineContentSpec(
  blockConfig: CustomInlineContentConfig,
  blockImplementation: ReactInlineContentImplementation,
);

Let's look at our custom mentions tag from the demo, and go over each field to explain how it works:

const Mention = createReactInlineContentSpec(
  {
    type: "mention",
    propSchema: {
      user: {
        default: "Unknown",
      },
    },
    content: "none",
  } as const,
  {
    render: (props) => (
      ...
    ),
  }
);

Inline Content Config (CustomInlineContentConfig)

The Inline Content Config describes the shape of your custom inline content. Use it to specify the type, properties (props) and content your custom inline content should support:

type CustomInlineContentConfig = {
  type: string;
  content: "styled" | "none";
  readonly propSchema: PropSchema;
  draggable?: boolean;
};

type: Defines the identifier of the custom inline content.

content: styled if your custom inline content should contain StyledText, none if not.

In the mentions demo, we want each mention to be a single, non-editable element, so we set content to "none".

propSchema: The PropSchema specifies the props that the inline content supports. Inline content props (properties) are data stored with your inline content in the document, and can be used to customize its appearance or behavior.

type PropSchema<PrimitiveType extends "boolean" | "number" | "string"> = Record<
  string,
  | {
      default: PrimitiveType;
      values?: PrimitiveType[];
    }
  | {
      default: undefined;
      type: PrimitiveType;
      values?: PrimitiveType[];
    }
>;

[key: string] is the name of the prop. If you want it to have a default value, it should be defined as an object with the following properties:

  • default: Specifies the prop's default value, from which PrimitiveType is inferred.

  • values?: Specifies an array of values that the prop can take, for example, to limit the value to a list of pre-defined strings. If values is not defined, BlockNote assumes the prop can be any value of PrimitiveType.

If you do not want the prop to have a default value, you can define it as an object with the following properties:

  • default: Left undefined, as there is no default value.

  • type: Specifies PrimitiveType that the prop can be set to, since the default value is undefined and cannot be inferred from.

  • values?: Specifies an array of values that the prop can take, for example, to limit the value to a list of pre-defined strings. If values is not defined, BlockNote assumes the prop can be any value of PrimitiveType.

In the mentions demo, we add a user prop for the user that's being mentioned.

draggable?: Whether the inline content should be draggable.

Inline Content Implementation (ReactCustomInlineContentImplementation)

The Inline Content Implementation defines how the inline content should be rendered to HTML.

type ReactCustomInlineContentImplementation = {
  render: React.FC<{
    inlineContent: InlineContent;
    contentRef?: (node: HTMLElement | null) => void;
    draggable?: boolean;
  }>;
};

render: This is your React component which defines how your custom inline content should be rendered, and takes three React props:

  • inlineContent: The inline content that should be rendered. Its type and props will match the type and PropSchema defined in the Inline Content Config.

  • contentRef: A React ref you can use to mark which element in your inline content is editable, this is only available if your inline content config contains content: "styled".

  • draggable: Specifies whether the inline content can be dragged within the editor. If set to true, the inline content will be draggable. Defaults to false if not specified. If this is true, you should add data-drag-handle to the DOM element that should function as the drag handle.

Note that since inline content is, by definition, inline, your component should also return an HTML inline element.

Adding Custom Inline Content to the Editor

Finally, create a BlockNoteSchema using the definition of your custom inline content:

const schema = BlockNoteSchema.create({
  inlineContentSpecs: {
    // enable the default inline content if desired
    ...defaultInlineContentSpecs,

    // Add your own custom inline content:
    mention: Mention,
  },
});

You can then instantiate your editor with this custom schema, as explained on the Custom Schemas page.