@rozie-ui/tiptap-vue
| Install | |
|---|---|
npm install @rozie-ui/tiptap-vue |
|
| Latest Version: | 0.5.4 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 15, 2026 |
| Links: | GitHub · npm |
@rozie-ui/tiptap-vue
Idiomatic vue TipTap — a cross-framework rich-text editor component compiled from one Rozie source wrapping TipTap (the ProseMirror-based headless editor). Two-way html content binding, a batteries-included toolbar (or bring your own via the toolbar slot), a 25-verb imperative command handle, and editorProps/extensions passthroughs. This package is generated; do not edit src/ by hand.
Install
npm i @rozie-ui/tiptap-vue
Peer dependencies: @tiptap/core, @tiptap/starter-kit, @tiptap/extensions and @tiptap/extension-bubble-menu (all ^3) + vue. Install them alongside this package. Optional, loaded only when used: @tiptap/extension-character-count (maxLength / #count), @tiptap/extension-image (uploadImage) and @tiptap/extension-floating-menu (the floatingMenu slot).
Usage
<script setup lang="ts">
import { ref } from 'vue';
import TipTap from '@rozie-ui/tiptap-vue';
const html = ref('<p>Hello <strong>world</strong></p>');
</script>
<template>
<TipTap v-model:html="html" placeholder="Start writing…" />
</template>
Props
| Name | Type | Default | Two-way (model) |
|---|---|---|---|
html |
String |
"<p>Start writing…</p>" |
✓ |
editable |
Boolean |
true |
|
placeholder |
String |
"" |
|
autofocus |
Boolean |
false |
|
editorClass |
String |
"" |
|
ariaLabel |
String |
"Rich text editor" |
|
editorProps |
Object |
{} |
|
extensions |
Array |
[] |
|
starterKit |
Object |
{} |
|
nodeSpecs |
Array |
[] |
|
uploadImage |
Function |
null |
|
maxLength |
Number |
null |
|
enforceMaxLength |
Boolean |
false |
|
bubbleMenuShouldShow |
Function |
null |
Events
| Event | Description |
|---|---|
update |
The document changed — payload is the new HTML string. |
selectionUpdate |
The selection (caret/range) moved. |
focus |
The editor gained focus. |
blur |
The editor lost focus. |
ready |
The editor exists — the live TipTap Editor instance. Fires once per mount. Handle verbs (focusEditor(), setContent(), …) work from here on; with an optional extension in use (maxLength, uploadImage, the floatingMenu slot) construction waits for its import, so this is the moment to act rather than a fixed delay. |
error |
An optional extension (floatingMenu, image, count) failed to load via dynamic import() — payload is { extension, error }. The editor still constructs WITHOUT that extension (degrade); a network blip never leaves a mounted <TipTap> permanently blank. |
Imperative handle
Beyond props, the component exposes imperative methods (declared once in the Rozie source via $expose). Grab a handle with the native ref mechanism and call them directly:
<script setup>
import { ref } from 'vue';
const editor = ref(); // template ref
</script>
<template>
<TipTap ref="editor" />
<button @click="editor.toggleBold()">Bold</button>
</template>
| Method | Description |
|---|---|
getEditor |
Return the underlying TipTap Editor instance for direct API access (commands, state, schema, extension storage). |
focusEditor |
Focus the editor — place the caret in the document. |
blurEditor |
Blur the editor — remove focus from the document. |
getHTML |
Return the current document serialized as an HTML string. |
getJSON |
Return the current document as a ProseMirror JSON object (JSONContent). |
getText |
Return the current document as a plain-text string (word/char counts, search indexing, plaintext export). |
setContent |
Replace the document content — setContent(html). Echo-guarded: reflects into the bound html model without bouncing an extra update. |
clearContent |
Clear the document to an empty paragraph (reflects the empty value into the bound html model). |
toggleBold |
Toggle bold on the current selection. |
toggleItalic |
Toggle italic on the current selection. |
toggleHeading |
Toggle a heading at the given level — toggleHeading(level) (defaults to 1). |
toggleBulletList |
Toggle a bullet list at the current selection. |
toggleUnderline |
Toggle underline on the current selection. |
toggleOrderedList |
Toggle an ordered (numbered) list at the current selection. |
undo |
Undo the last change. |
redo |
Redo the last undone change. |
chain |
Return a focused TipTap command chain for composing commands — e.g. chain().toggleBold().toggleItalic().run() (null before mount). |
isActive |
Whether a mark/node is active in the current selection — isActive(name, attrs?) (e.g. isActive("heading", { level: 2 })). Drives custom-toolbar active styling. False before mount. |
can |
Return the command-availability chain — can().chain().focus().toggleBold().run() returns a boolean — for enabling/disabling custom-toolbar buttons. null before mount. |
isEmpty |
Whether the document is empty — drives empty-state UI and submit-gating. true before mount. |
getCharacterCount |
Return the current character count. Reads the CharacterCount extension's live storage when registered (maxLength set or the #count slot filled), else falls back to getText().length. Always a number — 0 before mount. |
getWordCount |
Return the current word count. Reads the CharacterCount extension's live storage when registered, else falls back to a whitespace-split count of getText(). Always a number — 0 before mount. |
openLinkEditor |
Open the link editor on the current selection (create mode) — the imperative equivalent of clicking the toolbar Link button. Surfaces the editor prefilled with any existing link href; no-op before mount. |
setLink |
Apply or replace a link on the current selection, widening to the whole link mark first — setLink({ href }), with any additional stock attrs (target, rel, class, title) forwarded verbatim. An attrs object without a non-empty href is ignored. Attrs the registered Link extension does not declare are dropped by the extension itself — persisting a custom attribute requires Link.extend({ addAttributes }) via the extensions prop. No-op before mount. |
unsetLink |
Remove the link mark from the current selection, widening to the whole link first. No-op before mount. |
Slots
When you fill the toolbar slot the internal toolbar is replaced by your own UI, which receives the live editor so its buttons can drive editor.chain().focus()…run():
<template #toolbar="{ editor }"> … </template>
| Slot | Params |
|---|---|
| count | characters, words, maxLength, over |
| toolbar | editor |
| bubbleMenu | editor |
| floatingMenu | editor |
| linkEditor | editor, href, attrs, setLink, unsetLink, close |
| nodeView | node, selected, updateAttributes, getPos, editor, contentDOM |
Related Packages
A thin, batteries-included Vue 3 wrapper around Tiptap v3 — editor component, to...
Vue 2 adapter for Universal Rich Text Editor (Vue 2.6+ & 2.7)
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.5.4 | ^3.4 | MIT | |
| 0.5.3 | ^3.4 | MIT | |
| 0.5.2 | ^3.4 | MIT | |
| 0.5.1 | ^3.4 | MIT | |
| 0.4.0 | ^3.4 | MIT | |
| 0.3.2 | ^3.4 | MIT | |
| 0.3.1 | ^3.4 | MIT | |
| 0.3.0 | ^3.4 | MIT | |
| 0.2.1 | ^3.4 | MIT | |
| 0.2.0 | ^3.4 | MIT | |
| 0.1.1 | ^3.4 | MIT | |
| 0.1.0 | ^3.4 | MIT |