A modern, customizable rich-text editor for Angular applications, built with Tiptap and featuring complete internationalization support.
- Modern Angular: Built with Angular 18+ with Signals and modern patterns
- Rich Text Editing: Powered by Tiptap v3.3.0 with extensive formatting options
- Table Support: Full table management with bubble menus and cell selection
- Slash Commands: Intuitive slash commands for quick content insertion
- Internationalization: Full i18n support (English & French) with auto-detection
- Customizable: Highly configurable toolbar, bubble menus, and slash commands
- Image Support: Advanced image handling with resizing, compression, and bubble menus
- Height Control: Configurable editor height with scrolling
- Word/Character Count: Real-time word and character counting with proper pluralization
- Office Paste: Clean pasting from Microsoft Office applications
- TypeScript: Full TypeScript support with strict typing
- Accessibility: Built with accessibility best practices
- Service Architecture: Clean service-based architecture with
EditorCommandsService
npm install @flogeez/angular-tiptap-editor
Add the required CSS to your angular.json
file in the styles
array:
{
"styles": [
...
"node_modules/@fontsource/material-symbols-outlined/index.css",
"node_modules/@flogeez/angular-tiptap-editor/src/lib/styles/index.css",
...
]
}
import { Component } from "@angular/core";
import { AngularTiptapEditorComponent } from "@flogeez/angular-tiptap-editor";
@Component({
selector: "app-example",
standalone: true,
imports: [AngularTiptapEditorComponent],
template: `
<angular-tiptap-editor
[content]="content"
(contentChange)="onContentChange($event)"
/>
`,
})
export class ExampleComponent {
content = "<p>Hello <strong>World</strong>!</p>";
onContentChange(newContent: string) {
this.content = newContent;
console.log("Content updated:", newContent);
}
}
import { Component } from "@angular/core";
import {
AngularTiptapEditorComponent,
DEFAULT_TOOLBAR_CONFIG,
DEFAULT_BUBBLE_MENU_CONFIG,
} from "@flogeez/angular-tiptap-editor";
@Component({
selector: "app-advanced",
standalone: true,
imports: [AngularTiptapEditorComponent],
template: `
<angular-tiptap-editor
[content]="content"
[toolbar]="toolbarConfig"
[bubbleMenu]="bubbleMenuConfig"
[slashCommands]="slashCommandsConfig"
[locale]="'en'"
[height]="400"
[showCharacterCount]="true"
[showWordCount]="true"
(contentChange)="onContentChange($event)"
/>
`,
})
export class AdvancedComponent {
content = "<h1>Welcome!</h1><p>Start editing...</p>";
// Use default configurations as base
toolbarConfig = {
...DEFAULT_TOOLBAR_CONFIG,
clear: true, // Add clear button
};
bubbleMenuConfig = {
...DEFAULT_BUBBLE_MENU_CONFIG,
table: true, // Enable table bubble menu
};
slashCommandsConfig = {
commands: [], // Will be populated by the library
};
onContentChange(newContent: string) {
this.content = newContent;
}
}
import { Component } from "@angular/core";
import { FormControl, ReactiveFormsModule } from "@angular/forms";
import { AngularTiptapEditorComponent } from "@flogeez/angular-tiptap-editor";
@Component({
selector: "app-form",
standalone: true,
imports: [AngularTiptapEditorComponent, ReactiveFormsModule],
template: `
<form>
<angular-tiptap-editor
[formControl]="contentControl"
placeholder="Enter your content here..."
[showCharacterCount]="true"
[showWordCount]="true"
/>
<button type="submit">Submit</button>
</form>
`,
})
export class FormComponent {
contentControl = new FormControl("<p>Initial content</p>");
}
import { Component, inject } from "@angular/core";
import { EditorCommandsService } from "@flogeez/angular-tiptap-editor";
@Component({
selector: "app-commands",
standalone: true,
template: `
<div>
<button (click)="clearContent()">Clear Content</button>
<button (click)="focusEditor()">Focus Editor</button>
<button (click)="setContent()">Set Content</button>
</div>
`,
})
export class CommandsComponent {
private editorCommandsService = inject(EditorCommandsService);
private editor: Editor | null = null;
onEditorCreated(editor: Editor) {
this.editor = editor;
}
clearContent() {
if (this.editor) {
this.editorCommandsService.clearContent(this.editor);
}
}
focusEditor() {
if (this.editor) {
this.editorCommandsService.focus(this.editor);
}
}
setContent() {
if (this.editor) {
this.editorCommandsService.setContent(
this.editor,
"<h1>New Content</h1>"
);
}
}
}
Full table support with intuitive bubble menus:
- Table Creation: Insert tables via slash commands (
/table
) - Cell Selection: Click and drag to select multiple cells
- Bubble Menus: Context-aware menus for table operations
- Row/Column Management: Add, remove, and merge cells
- Styling: Custom table styling with proper borders
Quick content insertion with slash commands:
- Headings:
/h1
,/h2
,/h3
- Lists:
/bullet
,/numbered
- Blocks:
/quote
,/code
,/line
- Media:
/image
,/table
- Fully Internationalized: All commands translated
Professional image management:
- Drag & Drop: Drag images directly into the editor
- File Selection: Click to select images from device
- Auto-Compression: Images automatically compressed (max 1920x1080)
- Resizable: Images can be resized with handles
- Bubble Menu: Context menu for image operations
Real-time content statistics:
- Live Updates: Counters update as you type
- Proper Pluralization: "1 word" vs "2 words"
- Separate Counts: Independent word and character counts
- Configurable: Show/hide individual counters
Try the interactive demo online: https://flogeez.github.io/angular-tiptap-editor/
git clone https://github.com/FloGeez/angular-tiptap-editor.git
cd angular-tiptap-editor
npm install
npm start
Open http://localhost:4200 to view the demo.
Input | Type | Default | Description |
---|---|---|---|
content |
string |
"" |
Initial HTML content |
placeholder |
string |
"Start typing..." |
Placeholder text |
locale |
'en' | 'fr' |
Auto-detect | Editor language |
editable |
boolean |
true |
Whether editor is editable |
height |
number |
undefined |
Fixed height in pixels |
maxHeight |
number |
undefined |
Maximum height in pixels |
minHeight |
number |
200 |
Minimum height in pixels |
showToolbar |
boolean |
true |
Show toolbar |
showBubbleMenu |
boolean |
true |
Show bubble menu |
showCharacterCount |
boolean |
true |
Show character counter |
showWordCount |
boolean |
true |
Show word counter |
toolbar |
ToolbarConfig |
All enabled | Toolbar configuration |
bubbleMenu |
BubbleMenuConfig |
All enabled | Bubble menu configuration |
slashCommands |
SlashCommandsConfig |
All enabled | Slash commands configuration |
Output | Type | Description |
---|---|---|
contentChange |
string |
Emitted when content changes |
editorCreated |
Editor |
Emitted when editor is created |
editorFocus |
{editor, event} |
Emitted when editor gains focus |
editorBlur |
{editor, event} |
Emitted when editor loses focus |
import {
DEFAULT_TOOLBAR_CONFIG,
DEFAULT_BUBBLE_MENU_CONFIG,
SLASH_COMMAND_KEYS,
} from "@flogeez/angular-tiptap-editor";
// Minimal toolbar
const minimalToolbar = {
bold: true,
italic: true,
bulletList: true,
};
// Full toolbar with clear button
const fullToolbar = {
...DEFAULT_TOOLBAR_CONFIG,
clear: true, // Add clear button
};
// Bubble menu with table support
const bubbleMenuWithTable = {
...DEFAULT_BUBBLE_MENU_CONFIG,
table: true, // Enable table bubble menu
};
// Slash commands configuration
const slashCommands = {
commands: [], // Will be populated by filterSlashCommands()
};
// Available slash command keys
console.log(SLASH_COMMAND_KEYS); // ["heading1", "heading2", "heading3", "bulletList", "orderedList", "blockquote", "code", "image", "horizontalRule", "table"]
The editor supports English and French with automatic browser language detection:
// Force English
<angular-tiptap-editor [locale]="'en'" />
// Force French
<angular-tiptap-editor [locale]="'fr'" />
// Auto-detect (default)
<angular-tiptap-editor />
- English (en): Default language with complete translations
- French (fr): Full French translation including:
- Toolbar buttons
- Bubble menu items
- Slash commands
- Placeholder text
- Error messages
- Word/character count (with proper pluralization)
import {
filterSlashCommands,
SLASH_COMMAND_KEYS,
} from "@flogeez/angular-tiptap-editor";
// Filter available slash commands
const activeCommands = new Set(["heading1", "heading2", "bulletList", "table"]);
const commands = filterSlashCommands(activeCommands);
// Use in component
slashCommandsConfig = {
commands: commands,
};
The library follows a clean service-based architecture:
EditorCommandsService
: Centralized service for all editor commandsTiptapI18nService
: Internationalization service with automatic language detectionImageService
: Advanced image handling with compression and resizingfilterSlashCommands()
: Utility function for managing slash commands
- Signals: Used throughout for reactive state management
- Dependency Injection: Clean service injection with
inject()
- Standalone Components: All components are standalone for better tree-shaking
- TypeScript: Strict typing with comprehensive interfaces
The library provides default configurations that can be imported and customized:
import {
DEFAULT_TOOLBAR_CONFIG,
DEFAULT_BUBBLE_MENU_CONFIG,
DEFAULT_IMAGE_BUBBLE_MENU_CONFIG,
DEFAULT_TABLE_MENU_CONFIG,
SLASH_COMMAND_KEYS,
} from "@flogeez/angular-tiptap-editor";
npm run build:lib
npm run dev
This runs the library in watch mode and starts the demo application.
npm start
- Start demo applicationnpm run build
- Build demo applicationnpm run build:lib
- Build librarynpm run watch:lib
- Watch library changesnpm run dev
- Development mode (watch + serve)
MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- ๐ฎ Live Demo
- ๐ Tiptap Documentation
๐ ฐ๏ธ Angular Documentation- ๐ฆ NPM Package
- ๐ Report Issues
- ๐ก Feature Requests
- โ Table Support: Full table management with bubble menus
- โ Slash Commands: Intuitive content insertion commands
- โ Word/Character Count: Real-time counting with proper pluralization
- โ
Service Architecture: Clean
EditorCommandsService
for better maintainability - โ Default Configurations: Importable default configs for easy customization
- โ Office Paste: Clean pasting from Microsoft Office applications
- โ Enhanced i18n: Improved internationalization with better architecture
Made with โค๏ธ by FloGeez