slash-editor
Guides

Block Kit

Every createBlockKit() option — what ships by default, and how to opt a block out.

createBlockKit(options?) is what useSlashEditor's blockKit option configures. Every M1/M2 block is individually opt-out-able with false, the same seam throughout:

Prop

Type

Opting a block out for a custom NodeView

A host that needs a real NodeView (React, Vue, …) opts the baseline node out and supplies its own via extend, keeping a single schema registration:

import { Image } from "@slash-editor/core";
import { ReactNodeViewRenderer } from "@tiptap/react";
import { ImageNodeView } from "@/components/nodes/image-node-view";

useSlashEditor({
  blockKit: {
    image: false,
    extend: [Image.extend({ addNodeView: () => ReactNodeViewRenderer(ImageNodeView) })],
  },
});

The Media & AI Node Views component ships exactly this pattern — adapter is always a prop, never a hardcoded mock.

Configuring StarterKit

The kit builds on Tiptap's StarterKit. starterKit forwards options to it for the extensions the kit leaves alone — drop the underline mark (with its Mod-u shortcut and ++text++ markdown), restyle the drop cursor, configure hard breaks:

useSlashEditor({
  blockKit: {
    starterKit: { underline: false, dropcursor: { color: "var(--primary)" } },
  },
});

Keys the kit owns are not accepted, so each setting has one place to live: heading is headingLevels, undoRedo is history (and collaboration), link and codeBlock are the kit's own options. blockquote stays off because Quote registers its own blockquote node, and gapcursor stays off so clicks in block margins focus the nearest text.

Slash items, block types, and bubble toolbar buttons hide themselves when their node or mark is missing, so starterKit: { bulletList: false } simply drops "Bulleted list". Disabling a node other nodes' content requires — listItem while bulletList/orderedList stay on, or paragraph — throws a schema error.

No-default options

mention, ai, and collaboration have no default provider/adapter, so they stay unregistered until you pass one — see the mentions, AI stream adapter, and collaboration guides.

emoji and codeBlock are opt-in for a different reason: their dependencies are sizeable (the emoji dataset, lowlight's grammars). Each lives in its own entry, and the kit takes the node you build there instead of importing it, so neither reaches a bundle that leaves it out:

import { codeBlock } from "@slash-editor/core/code-block";
import { emoji } from "@slash-editor/core/emoji";

useSlashEditor({ blockKit: { emoji: emoji(), codeBlock: codeBlock() } });

Enabling emoji also converts typed :shortcode: text into emoji nodes — see the emoji guide. Left out, codeBlock is StarterKit's plain code block; a highlighted node (lowlight) replaces it under the same name. Pass your own lowlight instance to codeBlock() to choose the grammars, or see Code Block Node View for the language selector and token theme.

On this page