Skip to content

RichTextKit ​

RichTextKit is every feature of the editor as one Tiptap extension, the way StarterKit bundles Tiptap's basics. RichTextKitToolbar renders a complete toolbar and RichTextKitMenus the floating UI — the AI composer dock, the text bubble with the Improve menu, the table, link, media and block bubbles, the drag handle and the slash menu — for whatever the kit registered. Three imports, one working editor; switch a feature off and its button and menus go with it.

tsx
'use client';

import { EditorContent, useEditor } from '@tiptap/react';
import {
  RichTextKit,
  RichTextKitMenus,
  RichTextKitToolbar,
  RichTextProvider,
} from 'ai-sparkwrite-editor';
import 'ai-sparkwrite-editor/style.css';

export default function Editor() {
  const editor = useEditor({
    extensions: [
      RichTextKit.configure({
        ai: { endpoint: '/api/ai' }, // one URL on your backend
        image: { upload: (file) => uploadToYourStorage(file) },
        placeholder: { placeholder: 'Type / for blocks, Space on an empty line for AI…' },
        twitter: false,
      }),
    ],
    immediatelyRender: false,
  });

  if (!editor) return null;

  return (
    <RichTextProvider editor={editor}>
      <RichTextKitToolbar />
      <EditorContent editor={editor} />
      <RichTextKitMenus />
    </RichTextProvider>
  );
}
vue
<script setup lang="ts">
import { EditorContent, useEditor } from '@tiptap/vue-3';
import {
  RichTextKit,
  RichTextKitMenus,
  RichTextKitToolbar,
  RichTextProvider,
} from 'ai-sparkwrite-editor/vue';
import 'ai-sparkwrite-editor/style.css';

const editor = useEditor({
  extensions: [
    RichTextKit.configure({
      ai: { endpoint: '/api/ai' },
      image: { upload: (file) => uploadToYourStorage(file) },
      placeholder: { placeholder: 'Type something, or press Space on an empty line for AI…' },
    }),
  ],
});
</script>

<template>
  <RichTextProvider :editor="editor">
    <RichTextKitToolbar />
    <EditorContent :editor="editor" />
    <RichTextKitMenus />
  </RichTextProvider>
</template>

The kit is a convenience, not a lock-in: the same import exports every extension and control separately, and the RichTextKit* components work with an editor you assembled yourself — they only look at which extensions are registered. Because each feature keeps its own chunk, a kit with features switched off is not bigger than the same features imported one by one (see Bundle size).

Options ​

One key per feature. Three values:

  • omitted — the default: included, except for the opt-in features below;
  • false — left out, together with its toolbar button and menus;
  • an object — included and passed to that extension's .configure(); the object type is the extension's own options (ai: { endpoint }, codeBlock: { defaultLanguage: 'ts' }, heading: { levels: [1, 2, 3] }). For an opt-in feature the object switches it on — {} is enough when it needs nothing.
GroupKeys (default on)Opt-in keys ({ … } switches on)
Documentdocument, paragraph, text, hardBreak, dropcursor, gapcursor, historyplaceholder ({ placeholder: '…' })
Text stylebold, italic, underline, strike, code, moreMark (super/subscript), textStyle (the mark colours, fonts and sizes hang on), color, highlight, fontFamily, fontSize, lineHeight, textAlign, textDirection, indent, clear, formatPainter (React), link—
Blocksheading, bulletList, orderedList, taskList, blockquote, table, divider, details, codeBlock, callout, notice, tableOfContents, column (React; opt-in in Vue)horizontalRule (the divider replaces it)
Media and embedsimage, video, iframe, attachment, katex, mermaidimageGif ({ GIPHY_API_KEY }), emoji, excalidraw, drawer, twitter, mention ({ suggestion }), shortMessage ({ messages }) — React only, except imageGif
BehaviourslashCommand (React), searchAndReplace, richPaste, markdownPaste, exportMarkdown, exportWord, importWord, exportPdf, codeViewrecorder
AIai (options; set endpoint), aiAutocomplete—

Lists bring ListItem along, column widens the document schema to (block|columns)+, and every extension is registered once even when two keys share a companion. RichTextKitOptions is exported for typing a config you keep elsewhere.

The toolbar ​

<RichTextKitToolbar /> lays out: AI · undo, redo · heading · bold, italic, underline, strike, colour, highlight, clear · bullet, ordered and task lists, alignment · link, image, table, code block · a More tools panel with the rest (font family, font size, line height, super/subscript, indent, format painter; blockquote, inline code, divider, columns, callout, details, table of contents, emoji, video, GIF, attachment, iframe, Katex, Excalidraw, Mermaid, drawer, Twitter; import Word, export PDF / Word / Markdown; search & replace, text direction, source view). Every control appears only when its extension is registered.

The panel lays its rows out three per line, related ones side by side (font size · line height · format painter; indent · outdent…). Drag a row onto the toolbar to pin it there — it leaves the panel and gets a permanent button. To remove it, hover the button and click its × badge, use the "On the Toolbar" group at the bottom of the panel, or drag it back onto the panel. Pins are remembered per browser in localStorage.

PropDefaultPurpose
moretrueThe "More tools" panel
pinnabletrueDrag rows out of the panel onto the toolbar, and back
defaultPins[]Panel keys pinned until the user changes them, e.g. ['fontSize', 'katex']
storageKeyai-sparkwrite-editor:kit-toolbar-pinsWhere the pins are stored
children—Extra controls, placed after the built-in groups (React); the default slot in Vue
className—React: extra classes on the toolbar

For a different order or a hand-picked set, compose your own from the controls — see Toolbar.

The menus ​

<RichTextKitMenus /> mounts, for the registered extensions: RichTextAIComposer, RichTextBubbleText (with the Improve menu), the table, link, image, video, GIF, callout, iframe, Katex, Mermaid, Excalidraw, drawer and Twitter bubbles, RichTextBubbleMenuDragHandle and SlashCommandList (React). In Vue: the composer and the text, table, link and image bubbles.

PropDefaultPurpose
composertrueThe AI composer dock; false hides it, an object passes its props ({ defaultOpen: true, rows: 3 })
dragHandletrueThe block drag handle (React)

Playground ​

The playground runs on the kit by default; its Setup switch shows the same editor Assembled control by control — in React and in Vue.

Made with ❤️