Overview
RichTextEditor provides a full-featured rich text editing experience built on TipTap (ProseMirror). It supports markdown shortcuts, image paste/drop, and exposes imperative methods via ref.
Key Features
- Built on TipTap/ProseMirror for robust, extensible editing
- Markdown shortcuts (bold, italic, headings, lists, quotes, code)
- Image paste from clipboard and drag-drop support
- Imperative ref API (focus, clear, getHTML, getText)
Examples
Basic Example
Type in the editor below. Try markdown shortcuts like **bold**, *italic*, or # heading.
Markdown Shortcuts
Type markdown syntax and it converts automatically. Start a line with # for headings, - for lists, > for quotes.
**bold**Bold*italic*Italic~~strike~~Strikethrough# HeadingH1## HeadingH2- itemBullet list1. itemNumbered list> quoteBlockquote`code`Inline codeControlled Value
Use the value prop for controlled components. Content can be reset programmatically.
Disabled State
Disabled editors show a muted background and prevent all interaction.
Image Support
Paste or drag-drop images. By default converted to base64; use onImagePaste for server upload.
Props Reference
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Editor content as HTML string |
onChange | (html, text) => void | - | Callback when content changes, receives (html, text) |
placeholder | string | - | Placeholder text when editor is empty |
disabled | boolean | false | Whether the editor is disabled |
className | string | - | Additional CSS classes for the container |
minHeight | string | - | Minimum height of the editor area |
onImagePaste | (file: File) => Promise<string> | - | Async function to handle image paste, returns URL string |
Ref Methods (RichTextEditorRef)
| Prop | Type | Description |
|---|---|---|
editor | Editor | null | Direct access to TipTap editor instance |
focus() | () => void | Focus the editor |
clear() | () => void | Clear all content |
getHTML() | () => string | Get current content as HTML |
getText() | () => string | Get current content as plain text |
Future Extensions
The rich-text component is architected for extensibility. Planned additions include:
- @mentions for users, programs, and projects
- Dynamic tokens like {user.name} for templates
- Rich embeds for links, media, and attachments
- Configurable toolbars for different use cases
Usage
import { RichTextEditor, type RichTextEditorRef } from '@/ui/components';
import { useRef, useState } from 'react';
const editorRef = useRef<RichTextEditorRef>(null);
const [content, setContent] = useState('');
<RichTextEditor
ref={editorRef}
value={content}
onChange={(html, text) => setContent(html)}
placeholder="Write something..."
minHeight="150px"
disabled={false}
onImagePaste={async (file) => {
// Upload file to server, return URL
const url = await uploadFile(file);
return url;
}}
/>
// Imperative methods via ref
editorRef.current?.focus(); // Focus the editor
editorRef.current?.clear(); // Clear all content
editorRef.current?.getHTML(); // Get content as HTML
editorRef.current?.getText(); // Get content as plain text