0
# Visual Enhancement
1
2
Extensions that provide visual feedback, styling, and placeholder functionality to enhance the editor user interface and user experience.
3
4
## Capabilities
5
6
### Focus Extension
7
8
Adds CSS classes to focused nodes for styling purposes, enabling visual highlighting of the currently focused editor content.
9
10
```typescript { .api }
11
/**
12
* Focus extension for highlighting focused nodes with CSS classes
13
*/
14
const Focus: Extension<FocusOptions>;
15
16
interface FocusOptions {
17
/** CSS class applied to focused nodes (default: 'has-focus') */
18
className: string;
19
/** Focus application mode (default: 'all') */
20
mode: 'all' | 'deepest' | 'shallowest';
21
}
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import { Focus } from "@tiptap/extensions/focus";
28
29
// Basic focus highlighting
30
const editor = new Editor({
31
extensions: [
32
Focus.configure({
33
className: 'has-focus',
34
mode: 'all',
35
}),
36
],
37
});
38
39
// Different focus modes
40
const deepestFocus = Focus.configure({
41
className: 'focused-element',
42
mode: 'deepest', // Only the deepest nested node gets the class
43
});
44
45
const shallowestFocus = Focus.configure({
46
className: 'focused-container',
47
mode: 'shallowest', // Only the shallowest node gets the class
48
});
49
```
50
51
**Focus Modes:**
52
- **`'all'`**: All nodes in the selection path receive the CSS class
53
- **`'deepest'`**: Only the deepest (most nested) node receives the class
54
- **`'shallowest'`**: Only the shallowest (top-level) node receives the class
55
56
### Drop Cursor Extension
57
58
Provides visual feedback during drag-and-drop operations by showing a cursor line where content will be dropped.
59
60
```typescript { .api }
61
/**
62
* Drop cursor extension for drag-and-drop visual feedback
63
*/
64
const Dropcursor: Extension<DropcursorOptions>;
65
66
interface DropcursorOptions {
67
/** Drop cursor color, or false to disable (default: 'currentColor') */
68
color?: string | false;
69
/** Drop cursor width in pixels (default: 1) */
70
width: number | undefined;
71
/** Custom CSS class for the drop cursor (default: undefined) */
72
class: string | undefined;
73
}
74
```
75
76
**Usage Examples:**
77
78
```typescript
79
import { Dropcursor } from "@tiptap/extensions/drop-cursor";
80
81
// Basic drop cursor
82
const editor = new Editor({
83
extensions: [
84
Dropcursor.configure({
85
color: '#ff0000',
86
width: 2,
87
}),
88
],
89
});
90
91
// Custom styled drop cursor
92
const customDropCursor = Dropcursor.configure({
93
color: false, // Disable default color
94
class: 'custom-drop-cursor', // Use CSS class for styling
95
});
96
97
// Themed drop cursor
98
const themedDropCursor = Dropcursor.configure({
99
color: 'var(--primary-color)',
100
width: 3,
101
});
102
```
103
104
### Placeholder Extension
105
106
Shows placeholder text in empty editors or empty nodes, providing helpful hints to users about expected content.
107
108
```typescript { .api }
109
/**
110
* Placeholder extension for showing hint text in empty content areas
111
*/
112
const Placeholder: Extension<PlaceholderOptions>;
113
114
interface PlaceholderOptions {
115
/** CSS class for empty editor (default: 'is-editor-empty') */
116
emptyEditorClass: string;
117
/** CSS class for empty nodes (default: 'is-empty') */
118
emptyNodeClass: string;
119
/** Placeholder content as string or function (default: 'Write something …') */
120
placeholder: string | ((props: PlaceholderProps) => string);
121
/** Show placeholder only when editor is editable (default: true) */
122
showOnlyWhenEditable: boolean;
123
/** Show placeholder only for currently focused node (default: true) */
124
showOnlyCurrent: boolean;
125
/** Include placeholder for child nodes (default: false) */
126
includeChildren: boolean;
127
}
128
129
```typescript { .api }
130
interface PlaceholderProps {
131
/** Current editor instance */
132
editor: Editor;
133
/** The node that would show the placeholder */
134
node: ProsemirrorNode;
135
/** Position of the node in the document */
136
pos: number;
137
/** Whether the node has anchor (selection) */
138
hasAnchor: boolean;
139
}
140
```
141
142
**Usage Examples:**
143
144
```typescript
145
import { Placeholder } from "@tiptap/extensions/placeholder";
146
147
// Basic placeholder
148
const editor = new Editor({
149
extensions: [
150
Placeholder.configure({
151
placeholder: 'Start typing your story...',
152
}),
153
],
154
});
155
156
// Dynamic placeholder based on context
157
const contextualPlaceholder = Placeholder.configure({
158
placeholder: ({ node, pos, editor }) => {
159
if (node.type.name === 'heading') {
160
return 'Enter a heading...';
161
}
162
if (node.type.name === 'paragraph') {
163
return 'Write a paragraph...';
164
}
165
return 'Type something...';
166
},
167
showOnlyCurrent: true,
168
includeChildren: false,
169
});
170
171
// Always-visible placeholder
172
const alwaysVisiblePlaceholder = Placeholder.configure({
173
placeholder: 'Content goes here',
174
showOnlyWhenEditable: false,
175
showOnlyCurrent: false,
176
});
177
178
// Nested content placeholders
179
const nestedPlaceholder = Placeholder.configure({
180
placeholder: 'Add content...',
181
includeChildren: true, // Show placeholders in nested empty nodes
182
emptyNodeClass: 'empty-content-block',
183
});
184
```
185
186
### Selection Extension
187
188
Adds CSS classes to selected text when the editor is not focused, allowing for custom selection styling.
189
190
```typescript { .api }
191
/**
192
* Selection extension for styling selected text when editor is unfocused
193
*/
194
const Selection: Extension<SelectionOptions> & {
195
/** Default export also available */
196
default: Extension<SelectionOptions>;
197
};
198
199
type SelectionOptions = {
200
/** CSS class applied to selected text (default: 'selection') */
201
className: string;
202
}
203
```
204
205
**Usage Examples:**
206
207
```typescript
208
import { Selection } from "@tiptap/extensions/selection";
209
210
// Basic selection styling
211
const editor = new Editor({
212
extensions: [
213
Selection.configure({
214
className: 'custom-selection',
215
}),
216
],
217
});
218
219
// Using default export
220
import SelectionExtension from "@tiptap/extensions/selection";
221
222
const editorWithDefault = new Editor({
223
extensions: [
224
SelectionExtension.configure({
225
className: 'highlighted-selection',
226
}),
227
],
228
});
229
```
230
231
**Selection Behavior:**
232
- Only applies when editor is **not** focused
233
- Ignores empty selections (collapsed cursors)
234
- Ignores node selections (entire nodes selected)
235
- Does not display during drag operations
236
- Automatically removed when editor regains focus