df-rtf-editor Component
df-rtf-editor is a rich text editor on TipTap. Its toolbar is built from Vuetify components, so it uses the application's theme and this library's translated strings.
Basic Usage
df-rtf-editor bound to a vue-forms field:
<h2>Welcome to RTF Editor</h2><p>This is a <strong>rich text editor</strong> component built on <a href="https://tiptap.dev/">TipTap</a>.</p><p>You can:</p><ul><li>Format text with <strong>bold</strong>, <em>italic</em>, and headings</li><li>Insert links, images, and tables</li><li>Create bulleted and numbered lists</li><li>And much more...</li></ul>
Features
- Binds a
@dynamicforms/vue-formselement, av-model, or neither - Headings, bold, italic, block quotes, bulleted and numbered lists
- Images: insert by URL, upload, or paste directly from the clipboard, embedded as base64
data:URIs, with drag-handle resizing - Tables, with row and column insertion/deletion
- Links, with an optional
downloadattribute - Pasting a Word or Google Docs selection: formatted text, embedded images and tables are pasted as structured content, without the source application's markup
- A "Style" dropdown applying named, class-based styles to the current block or selection
- Media embeds: paste a YouTube or Vimeo URL to insert a responsive player
Props
In addition to common props from InputBase, this component supports:
| Prop | Type | Default | Description |
|---|---|---|---|
| minHeight | string | '7em' | Minimum height of the editing area |
| fontFamily | string | 'inherit' | font-family of the editing area and its named block styles. The component loads no font of its own; pass a value here (and load the font itself, if needed) to use something other than the surrounding page's font |
Inherited Props
This component inherits all common props from InputBase, including:
control- DynamicForms field objectmodelValue- The HTML content (v-model)label- Input labelhint- Hint text- And more...
Toolbar Features
Text formatting
- Bold, italic
- Headings (paragraph, H1-H6)
Structured content
- Bulleted and numbered lists, with indent/outdent
- Tables — insert, and add/delete rows and columns
- Block quotes, horizontal line
Links, images and media
- Links, with an optional "Downloadable" attribute (
download="file") - Images — insert by URL, upload from disk, or paste from the clipboard; all three embed the picture as a base64
data:URI, and a placed image can be resized by dragging its corner and edge handles - Media embed — paste a YouTube or Vimeo URL to insert a responsive
<iframe>player; any other URL is inserted as a plain link instead
- Links, with an optional "Downloadable" attribute (
Style dropdown
- Applies one of the named styles from Custom Styles to the current block or selection, and removes it on a second click
Alignment
- Left, center, right, justify
Utilities
- Undo/redo, select all
- A selection popup with bold, italic, link and list toggles
- Pasting from Word or Google Docs: formatting, embedded images and tables are pasted as structured content, without the source application's markup
Events
This component emits all common events from InputBase:
update:modelValue- When the HTML content changes
Working with HTML Content
The value is HTML, and the component does not sanitize it. An application that displays HTML entered by users sanitizes it first, to prevent XSS.
List items and table cells save their text wrapped in a paragraph (<li><p>...</p></li>, <td><p>...</p></td>), so HTML rendered outside this component (a public page, a PDF export, a templated email) needs li p, td p, th p { margin: 0; } in its stylesheet; otherwise the browser's default paragraph margin adds space to every list item and cell. <df-rtf-editor>'s editing surface has this rule. See also the migration guide.
Custom Styles
The editor's stylesheet styles several predefined content classes, applied from the toolbar's Style dropdown:
| Style | Element | Class |
|---|---|---|
| Article category | h3 | category |
| Title | h2 | document-title |
| Subtitle | h3 | document-subtitle |
| Info box | p | info-box |
| Side quote | blockquote | side-quote |
| Marker | span (inline) | marker |
| Spoiler | span (inline) | spoiler |
| Code (dark) | pre | fancy-code fancy-code-dark |
| Code (bright) | pre | fancy-code fancy-code-bright |
The block-level styles (all but Marker and Spoiler) set the current block's element type and class; Marker and Spoiler toggle over a text selection like bold or italic. Clicking an applied style removes it: the block becomes a plain paragraph, or, for Marker and Spoiler, the mark is removed.
Examples
Basic Usage with v-model
<template>
<df-rtf-editor
v-model="content"
label="Article Content"
hint="Use the formatting toolbar to style your content"
/>
</template>
<script setup>
import { ref } from 'vue';
import { DfRtfEditor } from '@dynamicforms/vuetify-inputs';
const content = ref('<h2>Welcome</h2><p>This is a <strong>rich text editor</strong>.</p>');
</script>With DynamicForms Integration
<template>
<df-rtf-editor
:control="form.fields.description"
label="Product Description"
hint="Format the product description with rich text"
min-height="15em"
/>
</template>
<script setup>
import { Group, Field, ValidationError, Validators } from '@dynamicforms/vue-forms';
import { DfRtfEditor } from '@dynamicforms/vuetify-inputs';
const form = new Group({
description: new Field({
value: '<p>Enter a detailed product description here.</p>',
validators: [
new Validators.Validator((value) => {
if (!value || value === '<p></p>') return [new ValidationError('description_required', {}, 'Description is required')];
if (value.length < 20) return [new ValidationError('description_too_short', { minLength: 20 }, 'Description is too short')];
return null;
})
]
})
});
</script>