A modern rich text editor built with Tiptap v3, Radix UI, and Tailwind CSS v4. This is the React + Vite version of the reusable editor module.
Acknowledgments: Inspired by and adapted from ndtrung341/next-tiptap.
- Text: Bold, italic, underline, strike, code, sub/superscript, color, highlight, alignment
- Structure: Headings H1-H6, ordered/unordered lists, blockquotes, indent
- Media: Images (upload, resize, caption), YouTube embeds, tables (cell alignment, merge/split)
- Code: Syntax-highlighted code blocks via Shiki (dual light/dark theme)
- Tools: Drag & drop blocks, fullscreen, HTML source view (CodeMirror), Word (.docx) export
- Rendering: Client-side renderer for read-only display (
/preview) - Theming: Pure CSS variables (
--rte-*) with dark mode toggle
/: Editor page (ActionBar + PostForm + autosave + export)/preview: Read-only preview page
git clone https://github.com/vanthuan52/react-tiptap
cd react-tiptap
npm install
npm run devOpen http://localhost:5173.
npm run dev # Start Vite dev server
npm run build # Type-check + production build
npm run preview # Preview production build
npm run lint # Run ESLintCreate .env (or .env.local) from .env.example:
VITE_CLOUDINARY_CLOUD_NAME=your_cloud_name
VITE_CLOUDINARY_API_KEY=your_api_key
VITE_CLOUDINARY_API_SECRET=your_api_secret
VITE_CLOUDINARY_UPLOAD_PRESET=your_upload_presetNotes:
- The media library reads Cloudinary config from
src/configs/app.config.ts. - If you use Cloudinary asset listing/upload from the editor dialog, provide your own API endpoints compatible with
GET /api/imagesandPOST /api/images.
The core module lives in src/features/tiptap-editor/. You can copy this folder to another project and use it as a standalone feature module. Follow the Module Documentation for setup.
import { useRef } from "react";
import TiptapEditor, { type TiptapEditorRef } from "./features/tiptap-editor";
export default function MyEditor() {
const editorRef = useRef<TiptapEditorRef>(null);
return (
<TiptapEditor
ref={editorRef}
output="html"
minHeight={320}
placeholder={{ paragraph: "Start typing..." }}
onChange={(html) => console.log(html)}
/>
);
}Do not forget global imports in your app entry:
import "./styles/globals.css";
import "./features/tiptap-editor/styles/index.css";| Technology | Version |
|---|---|
| Vite | 8 |
| React | 19 |
| Tiptap | v3 |
| Radix UI | Latest |
| Tailwind CSS | v4 |
| Shiki | 4 |
| CodeMirror | 6 |
| TypeScript | 6 |
Built with React, Vite, and Tiptap
