scribex-editor
v1.1.0
Published
A modern, feature-rich WYSIWYG editor for React built on TipTap and shadcn/ui
Maintainers
Readme
✍️ Scribex Editor
A modern, feature-rich WYSIWYG editor for React — built on TipTap and shadcn/ui.
Drop-in rich text editor with 30+ toolbar components, dark mode, themes, slash commands, and AI-friendly content output.
🧩 What it includes
| Feature | Description | |---------|-------------| | ✍️ | Rich text formatting — bold, italic, underline, strike, code | | 📋 | Headings & lists — H1–H6, bullet, ordered, task lists | | 🖼️ | Media — images, videos, GIFs (Giphy), file attachments | | 📐 | Layout — tables, multi-column, horizontal rules, blockquotes | | 💻 | Code — syntax-highlighted code blocks, inline code, code view | | 🧮 | Advanced — math equations (KaTeX), Mermaid diagrams, Excalidraw whiteboard | | 🐦 | Embeds — Twitter/X, iframes, drawing tool | | 🔍 | Productivity — slash commands, @mentions, search & replace, character count | | 🎨 | Theming — dark/light mode, 8 color themes, custom border radius | | 🌍 | i18n — English, Vietnamese, Simplified Chinese, Brazilian Portuguese, Hungarian, Finnish | | 📄 | Export/Import — PDF export, Word export, Word import |
📦 Installation
Requirements
- React v18 or higher
- Node.js v18 or higher
Install
npm install scribex-editor
# or
pnpm add scribex-editor
# or
yarn add scribex-editorImport styles
Add both stylesheets to your app entry point:
import 'scribex-editor/styles.css';
import 'reactjs-tiptap-editor/style.css';🚀 Quick Start
import { ScribexEditor, ScribexThemeProvider } from 'scribex-editor';
import 'scribex-editor/styles.css';
import 'reactjs-tiptap-editor/style.css';
function App() {
return (
<ScribexThemeProvider>
<ScribexEditor
initialContent="<p>Start typing...</p>"
onChange={(content) => console.log(content)}
/>
</ScribexThemeProvider>
);
}Next.js users: Add
"use client"at the top of any file that importsScribexEditor— it requires browser APIs.
🎨 Theme Customization
Provider configuration
<ScribexThemeProvider
defaultConfig={{
mode: 'dark', // 'light' | 'dark'
color: 'blue', // see color options below
borderRadius: 0.5, // 0–1
locale: 'en', // see locale options below
}}
>
<ScribexEditor ... />
</ScribexThemeProvider>Available colors
| Value | Preview |
|-------|---------|
| default | Neutral gray |
| red | Red accent |
| blue | Blue accent |
| green | Green accent |
| orange | Orange accent |
| rose | Rose accent |
| violet | Violet accent |
| yellow | Yellow accent |
Available locales
| Value | Language |
|-------|----------|
| en | English |
| vi | Vietnamese |
| zh_CN | Simplified Chinese |
| pt_BR | Brazilian Portuguese |
| hu_HU | Hungarian |
| fi | Finnish |
Dynamic theme switching
import { useScribexTheme } from 'scribex-editor';
function ThemeControls() {
const { mode, setMode, color, setColor } = useScribexTheme();
return (
<div>
<button onClick={() => setMode(mode === 'light' ? 'dark' : 'light')}>
Toggle {mode === 'light' ? 'Dark' : 'Light'} Mode
</button>
<select value={color} onChange={(e) => setColor(e.target.value as ThemeColor)}>
{['default','red','blue','green','orange','rose','violet','yellow'].map(c => (
<option key={c} value={c}>{c}</option>
))}
</select>
</div>
);
}⚙️ Props Reference
<ScribexEditor>
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| initialContent | string | '' | Initial HTML content |
| onChange | (content: string) => void | — | Fires on content change (debounced) |
| onEditorReady | (editor: Editor) => void | — | Fires when editor is initialized |
| placeholder | string | "Press '/' for commands" | Placeholder text |
| characterLimit | number | 10000 | Maximum character limit |
| editable | boolean | true | Enable or disable editing |
| className | string | — | Class on the container element |
| toolbarClassName | string | — | Class on the toolbar element |
| contentClassName | string | — | Class on the content area |
| imageUpload | (file: File) => Promise<string> | — | Custom image upload handler; return the URL |
| videoUpload | (file: File) => Promise<string> | — | Custom video upload handler; return the URL |
| attachmentUpload | (file: File) => Promise<string> | — | Custom attachment upload handler; return the URL |
| giphyApiKey | string | — | Giphy API key to enable GIF search |
| mentionUsers | Array<{id, label, avatar?}> | [] | Users available for @mentions |
| showToolbar | boolean | true | Show or hide the toolbar |
| showBubbleMenus | boolean | true | Show or hide bubble menus on selection |
| showSlashCommands | boolean | true | Enable / slash command palette |
| showCharacterCount | boolean | true | Show character count indicator |
| debounceMs | number | 300 | Debounce delay for onChange (ms) |
<ScribexThemeProvider>
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| defaultConfig | ScribexThemeConfig | — | Initial theme settings |
| children | ReactNode | — | Required — wrap your editor here |
<EditorPreview>
Read-only display of HTML content with the same styles as the editor.
import { EditorPreview } from 'scribex-editor';
<EditorPreview content="<p>Hello <strong>World</strong></p>" />🔌 Editor Instance
Access the TipTap editor instance directly via onEditorReady:
import { ScribexEditor } from 'scribex-editor';
import type { Editor } from 'scribex-editor';
function App() {
const handleEditorReady = (editor: Editor) => {
editor.commands.insertContent('<p>Injected content</p>');
editor.commands.focus();
};
return <ScribexEditor onEditorReady={handleEditorReady} />;
}🛠️ Custom Toolbar
Build a fully custom toolbar by composing individual toolbar components:
import {
ScribexEditor,
ScribexThemeProvider,
RichTextBold,
RichTextItalic,
RichTextHeading,
RichTextBulletList,
RichTextOrderedList,
RichTextLink,
RichTextImage,
RichTextUndo,
RichTextRedo,
} from 'scribex-editor';
function App() {
return (
<ScribexThemeProvider>
<ScribexEditor
showToolbar={false} // hide the built-in toolbar
onChange={(c) => console.log(c)}
/>
</ScribexThemeProvider>
);
}All available toolbar components
| Component | Description |
|-----------|-------------|
| RichTextBold | Bold |
| RichTextItalic | Italic |
| RichTextUnderline | Underline |
| RichTextStrike | Strikethrough |
| RichTextCode | Inline code |
| RichTextCodeBlock | Code block |
| RichTextLink | Hyperlink |
| RichTextImage | Image |
| RichTextVideo | Video |
| RichTextImageGif | GIF (Giphy) |
| RichTextBlockquote | Blockquote |
| RichTextBulletList | Bullet list |
| RichTextOrderedList | Ordered list |
| RichTextTaskList | Task / checklist |
| RichTextHeading | Headings H1–H6 |
| RichTextUndo / RichTextRedo | History |
| RichTextColor | Text color |
| RichTextHighlight | Background highlight |
| RichTextAlign | Text alignment |
| RichTextIndent | Indent / outdent |
| RichTextFontFamily | Font family |
| RichTextFontSize | Font size |
| RichTextLineHeight | Line height |
| RichTextTable | Table |
| RichTextColumn | Multi-column layout |
| RichTextEmoji | Emoji picker |
| RichTextKatex | Math equations (KaTeX) |
| RichTextMermaid | Mermaid diagrams |
| RichTextExcalidraw | Excalidraw whiteboard |
| RichTextDrawer | Drawing tool |
| RichTextIframe | Iframe embed |
| RichTextTwitter | Twitter / X embed |
| RichTextCallout | Callout block |
| RichTextAttachment | File attachment |
| RichTextExportPdf | Export to PDF |
| RichTextImportWord | Import from Word |
| RichTextExportWord | Export to Word |
| RichTextSearchAndReplace | Search and replace |
| RichTextClear | Clear formatting |
| RichTextMoreMark | More marks menu |
| RichTextTextDirection | Text direction (RTL/LTR) |
| RichTextCodeView | HTML source view |
| RichTextHorizontalRule | Horizontal rule |
📁 Project Structure
scribex-editor/
├── src/
│ ├── components/
│ │ ├── ScribexEditor.tsx # Main TipTap-based editor component
│ │ ├── RichTextEditor.tsx # Quill-based alternative editor
│ │ ├── EditorPreview.tsx # Read-only content preview
│ │ ├── ThemeProvider.tsx # React Context for theming & locale
│ │ └── index.ts
│ ├── utils/
│ │ ├── cn.ts # Class name utility (clsx + tailwind-merge)
│ │ ├── helpers.ts # debounce, createObjectURL, base64 helpers
│ │ └── index.ts
│ ├── emojis.ts # EMOJI_LIST data
│ └── index.ts # Public API barrel export
├── dist/ # Compiled output (git-ignored)
├── package.json
├── tsup.config.ts
└── tsconfig.json🛠️ Development
# Clone the repo
git clone https://github.com/mirzasaikatahmmed/scribex-editor.git
cd scribex-editor
# Install dependencies
npm install
# Build the package
npm run build
# Watch mode (rebuilds on save)
npm run dev📋 Changelog
See CHANGELOG.md for the full version history.
v1.0.8 — Current
- 📝 Full open source documentation suite (CONTRIBUTING, CODE_OF_CONDUCT, REPOSITORY_RULES, CHANGELOG)
- ✨ Complete Next.js 15 + React 19 demo app with live theme controls and HTML output panel
v1.0.7
- 🔒 Security: malware scanner script and GitHub Actions workflow added
v1.0.5
- 🛠️ Tailwind config path fixes and
.gitignorecleanup
v1.0.4
- 📝 README documentation improvements
v1.0.3
- 🚀 CI/CD publish workflow stabilised
v1.0.2
- ✨ Added
RichTextEditor(Quill-based) andEditorPreviewcomponents - 🏗️ Repo flattened from pnpm monorepo to single npm package
v1.0.0
- 🎉 Initial release —
ScribexEditor,ScribexThemeProvider, 30+ toolbar components, 6 locales, full TipTap feature set
🤝 Contributing
Pull requests are welcome! For major changes, please open an issue first to discuss.
- Fork the repository
- Create your branch:
git checkout -b feat/your-feature - Make changes, build, and test
- Push and open a PR
Please read CONTRIBUTING.md for full guidelines and CODE_OF_CONDUCT.md before participating. All contributors are listed in CONTRIBUTORS.md.
💛 Support
If Scribex Editor saves you time, consider supporting the project:
Made with ❤️ by Mirza Saikat Ahmmed
