vue-wysiwyg-tiptap

Headless WYSIWYG editor for Vue 3 built on Tiptap 3, with slash commands, mentions, AI assist, and markdown paste.
3,400
Install
npm install vue-wysiwyg-tiptap
Latest Version:0.1.3
Vue:3
License:MIT
Last Updated:Feb 17, 2026
Links: GitHub  ·  npm
Maintainer: krimuthu

vue-wysiwyg-tiptap

A headless, extensible WYSIWYG rich-text editor for Vue 3 built on Tiptap 3. Ships with slash commands, @mentions, AI text assist, image upload, markdown paste, and a bubble menu — all out of the box.

alt text

Docs & Live Demos · npm · GitHub

Features

  • Slash commands — type / for headings, lists, blockquote, code block, image, horizontal rule
  • Bubble menu — bold, italic, underline, strikethrough, code, link editing on text selection
  • @mentions — autocomplete with a configurable member list
  • AI text assist — modify selected text with customizable AI quick actions
  • Image upload — file picker, paste, and drag & drop with custom upload handler
  • Markdown paste — paste markdown and it converts to rich text automatically
  • Task lists — interactive checkboxes
  • Fully headless — all styles are optional and overridable via vwt-* CSS classes

Install

npm install vue-wysiwyg-tiptap vue @tiptap/core @tiptap/vue-3 @tiptap/pm

Quick Start

<script setup>
import { ref } from 'vue'
import { WysiwygEditor } from 'vue-wysiwyg-tiptap'
import 'vue-wysiwyg-tiptap/styles/editor.css'

const content = ref('<p>Hello world!</p>')
</script>

<template>
  <WysiwygEditor v-model="content" />
</template>

Props

Prop Type Default Description
modelValue String '' v-model HTML content
members Array<{id, label}> [] Users for @mention autocomplete
onUploadImage (file: File) => Promise<string | null> null Image upload handler, return URL or null
onImageUploadError (message: string) => void null Image upload error callback
onModifyText (html: string, instruction: string) => Promise<string> null AI text modification handler
aiQuickActions Array<{label, instruction}> See below Override AI quick action buttons
placeholder String "Type '/' for commands..." Editor placeholder text
extensions Array [] Additional Tiptap extensions

Default AI quick actions: Polish, Professional, Simplify, Expand, Fix Grammar.

Events

Event Payload Description
update:modelValue (html: string) Content changed (used automatically with v-model)
ready (editor: Editor) Tiptap editor instance is ready

Slots

Slot Scope Description
overlay { isUploading, isProcessing } Custom loading overlay
bubble-menu { editor } Replace the default bubble menu

Exposed Refs

Access via a template ref on <WysiwygEditor ref="editorRef">:

  • editorRef.editor — Tiptap Editor instance
  • editorRef.aiAssist — { isProcessing, showPanel, togglePanel, applyModification, ... }
  • editorRef.imageUpload — { isUploading, openFilePicker, ... }

Image Upload

<script setup>
import { ref } from 'vue'
import { WysiwygEditor } from 'vue-wysiwyg-tiptap'

const content = ref('')

async function handleUpload(file) {
  const form = new FormData()
  form.append('image', file)
  const res = await fetch('/api/upload', { method: 'POST', body: form })
  const { url } = await res.json()
  return url
}
</script>

<template>
  <WysiwygEditor v-model="content" :on-upload-image="handleUpload" />
</template>

Images can be inserted via slash command, paste, or drag & drop. Accepted types: JPEG, PNG, GIF, WebP.

AI Assist

<script setup>
import { ref } from 'vue'
import { WysiwygEditor } from 'vue-wysiwyg-tiptap'

const content = ref('')

async function handleModify(html, instruction) {
  const res = await fetch('/api/ai/modify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ html, instruction }),
  })
  const { result } = await res.json()
  return result
}

const actions = [
  { label: 'Summarize', instruction: 'Summarize in one sentence' },
  { label: 'Translate', instruction: 'Translate to French' },
]
</script>

<template>
  <WysiwygEditor
    v-model="content"
    :on-modify-text="handleModify"
    :ai-quick-actions="actions"
  />
</template>

Mentions

<template>
  <WysiwygEditor
    v-model="content"
    :members="[
      { id: '1', label: 'Alice Johnson' },
      { id: '2', label: 'Bob Smith' },
    ]"
  />
</template>

Type @ to trigger autocomplete. Up to 8 suggestions shown, filtered case-insensitively by label.

Styles

Two optional stylesheets are provided:

import 'vue-wysiwyg-tiptap/styles/editor.css'       // Editor UI (bubble menu, slash commands, etc.)
import 'vue-wysiwyg-tiptap/styles/rich-content.css'  // Typography for rendered HTML output

For rendered output, wrap your content in a .vwt-rich-content container:

<div class="vwt-rich-content" v-html="content" />

All CSS classes use the vwt- prefix and can be freely overridden. See the Styling guide for the full class reference.

Individual Exports

All components, extensions, composables, and utilities are individually importable:

import { SlashCommand, MentionExtension, ExitBlock, MarkdownPaste } from 'vue-wysiwyg-tiptap'
import { useEditorImageUpload, useEditorAIAssist } from 'vue-wysiwyg-tiptap'
import { isAllowedUrl, createSuggestionRenderer } from 'vue-wysiwyg-tiptap'

License

MIT

Related Packages

tiptap-vue-pro-core

Tiptap Vue Pro 的 UI 无关核心层:封装 Tiptap v3,提供 composable 与类型契约

3,174 8
@hmfw/tiptap-editor

基于 Tiptap + Vue 3 的富文本编辑器组件。

523 0
@abhinavakhil/penna-vue

Vue 3 bindings for @abhinavakhil/penna-core

307 0
@tessera-editor/vue

Tessera Vue 3 binding with the full default UI

235 0
@geelato/lite-editor

A lightweight, extensible rich text editor based on TipTap and Vue 3

3,428 0

Version History

Version Released Vue License
0.1.3 ^3.3.0 MIT
0.1.2 ^3.3.0 MIT
0.1.1 ^3.3.0 MIT
0.1.0 ^3.3.0 MIT