Collection of utility extensions for Tiptap rich text editor including character counting, placeholders, focus management, and history controls
—
Extensions that provide visual feedback, styling, and placeholder functionality to enhance the editor user interface and user experience.
Adds CSS classes to focused nodes for styling purposes, enabling visual highlighting of the currently focused editor content.
/**
* Focus extension for highlighting focused nodes with CSS classes
*/
const Focus: Extension<FocusOptions>;
interface FocusOptions {
/** CSS class applied to focused nodes (default: 'has-focus') */
className: string;
/** Focus application mode (default: 'all') */
mode: 'all' | 'deepest' | 'shallowest';
}Usage Examples:
import { Focus } from "@tiptap/extensions/focus";
// Basic focus highlighting
const editor = new Editor({
extensions: [
Focus.configure({
className: 'has-focus',
mode: 'all',
}),
],
});
// Different focus modes
const deepestFocus = Focus.configure({
className: 'focused-element',
mode: 'deepest', // Only the deepest nested node gets the class
});
const shallowestFocus = Focus.configure({
className: 'focused-container',
mode: 'shallowest', // Only the shallowest node gets the class
});Focus Modes:
'all': All nodes in the selection path receive the CSS class'deepest': Only the deepest (most nested) node receives the class'shallowest': Only the shallowest (top-level) node receives the classProvides visual feedback during drag-and-drop operations by showing a cursor line where content will be dropped.
/**
* Drop cursor extension for drag-and-drop visual feedback
*/
const Dropcursor: Extension<DropcursorOptions>;
interface DropcursorOptions {
/** Drop cursor color, or false to disable (default: 'currentColor') */
color?: string | false;
/** Drop cursor width in pixels (default: 1) */
width: number | undefined;
/** Custom CSS class for the drop cursor (default: undefined) */
class: string | undefined;
}Usage Examples:
import { Dropcursor } from "@tiptap/extensions/drop-cursor";
// Basic drop cursor
const editor = new Editor({
extensions: [
Dropcursor.configure({
color: '#ff0000',
width: 2,
}),
],
});
// Custom styled drop cursor
const customDropCursor = Dropcursor.configure({
color: false, // Disable default color
class: 'custom-drop-cursor', // Use CSS class for styling
});
// Themed drop cursor
const themedDropCursor = Dropcursor.configure({
color: 'var(--primary-color)',
width: 3,
});Shows placeholder text in empty editors or empty nodes, providing helpful hints to users about expected content.
/**
* Placeholder extension for showing hint text in empty content areas
*/
const Placeholder: Extension<PlaceholderOptions>;
interface PlaceholderOptions {
/** CSS class for empty editor (default: 'is-editor-empty') */
emptyEditorClass: string;
/** CSS class for empty nodes (default: 'is-empty') */
emptyNodeClass: string;
/** Placeholder content as string or function (default: 'Write something …') */
placeholder: string | ((props: PlaceholderProps) => string);
/** Show placeholder only when editor is editable (default: true) */
showOnlyWhenEditable: boolean;
/** Show placeholder only for currently focused node (default: true) */
showOnlyCurrent: boolean;
/** Include placeholder for child nodes (default: false) */
includeChildren: boolean;
}
```typescript { .api }
interface PlaceholderProps {
/** Current editor instance */
editor: Editor;
/** The node that would show the placeholder */
node: ProsemirrorNode;
/** Position of the node in the document */
pos: number;
/** Whether the node has anchor (selection) */
hasAnchor: boolean;
}Usage Examples:
import { Placeholder } from "@tiptap/extensions/placeholder";
// Basic placeholder
const editor = new Editor({
extensions: [
Placeholder.configure({
placeholder: 'Start typing your story...',
}),
],
});
// Dynamic placeholder based on context
const contextualPlaceholder = Placeholder.configure({
placeholder: ({ node, pos, editor }) => {
if (node.type.name === 'heading') {
return 'Enter a heading...';
}
if (node.type.name === 'paragraph') {
return 'Write a paragraph...';
}
return 'Type something...';
},
showOnlyCurrent: true,
includeChildren: false,
});
// Always-visible placeholder
const alwaysVisiblePlaceholder = Placeholder.configure({
placeholder: 'Content goes here',
showOnlyWhenEditable: false,
showOnlyCurrent: false,
});
// Nested content placeholders
const nestedPlaceholder = Placeholder.configure({
placeholder: 'Add content...',
includeChildren: true, // Show placeholders in nested empty nodes
emptyNodeClass: 'empty-content-block',
});Adds CSS classes to selected text when the editor is not focused, allowing for custom selection styling.
/**
* Selection extension for styling selected text when editor is unfocused
*/
const Selection: Extension<SelectionOptions> & {
/** Default export also available */
default: Extension<SelectionOptions>;
};
type SelectionOptions = {
/** CSS class applied to selected text (default: 'selection') */
className: string;
}Usage Examples:
import { Selection } from "@tiptap/extensions/selection";
// Basic selection styling
const editor = new Editor({
extensions: [
Selection.configure({
className: 'custom-selection',
}),
],
});
// Using default export
import SelectionExtension from "@tiptap/extensions/selection";
const editorWithDefault = new Editor({
extensions: [
SelectionExtension.configure({
className: 'highlighted-selection',
}),
],
});Selection Behavior:
Install with Tessl CLI
npx tessl i tessl/npm-tiptap--extensions