0
# Tiptap Focus Extension
1
2
The Focus extension allows you to add CSS classes to focused nodes in a Tiptap editor, providing visual focus indicators that enhance user experience and accessibility. It operates as a ProseMirror plugin that decorates nodes based on cursor position, offering three different focus modes for various use cases.
3
4
## Package Information
5
6
- **Package Name**: @tiptap/extensions/focus
7
- **Package Type**: npm (TypeScript extension)
8
- **Language**: TypeScript
9
- **Installation**: `npm install @tiptap/extensions`
10
11
## Core Imports
12
13
```typescript
14
import { Focus, FocusOptions } from "@tiptap/extensions";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { Focus, FocusOptions } = require("@tiptap/extensions");
21
```
22
23
Sub-path imports (also supported):
24
25
```typescript
26
import { Focus, FocusOptions } from "@tiptap/extensions/focus";
27
```
28
29
## Basic Usage
30
31
```typescript
32
import { Editor } from "@tiptap/core";
33
import { Focus } from "@tiptap/extensions";
34
35
// Basic usage with default options
36
const editor = new Editor({
37
extensions: [
38
Focus,
39
// ... other extensions
40
],
41
content: "<p>Your content here</p>",
42
});
43
44
// Custom configuration
45
const editor = new Editor({
46
extensions: [
47
Focus.configure({
48
className: 'is-focused',
49
mode: 'deepest',
50
}),
51
// ... other extensions
52
],
53
content: "<p>Your content here</p>",
54
});
55
```
56
57
## Architecture
58
59
The Focus extension integrates with Tiptap's extension system and uses ProseMirror's decoration API to efficiently add CSS classes to DOM elements without re-rendering content. Key components:
60
61
- **Extension Class**: Extends Tiptap's base Extension class with focus-specific configuration
62
- **ProseMirror Plugin**: Implements the actual focus detection and decoration logic
63
- **Decoration System**: Uses ProseMirror's DecorationSet for performant DOM manipulation
64
- **Focus Detection**: Analyzes document structure and cursor position to determine focused nodes
65
66
## Capabilities
67
68
### Focus Extension
69
70
Creates a Tiptap extension that adds CSS classes to focused nodes based on cursor position.
71
72
```typescript { .api }
73
import { Extension } from "@tiptap/core";
74
75
/**
76
* Focus extension that adds CSS classes to focused nodes
77
* Extends Tiptap's base Extension class with FocusOptions configuration
78
*/
79
const Focus: Extension<FocusOptions>;
80
```
81
82
### Focus Configuration
83
84
Configures the Focus extension with custom options.
85
86
```typescript { .api }
87
/**
88
* Configure the Focus extension with custom options
89
* @param options - Configuration options for focus behavior
90
* @returns Configured Focus extension instance
91
*/
92
Focus.configure(options: Partial<FocusOptions>): Extension<FocusOptions>;
93
```
94
95
### Focus Mode: All
96
97
Marks all nodes in the selection path as focused (default behavior).
98
99
```typescript
100
// Configuration for 'all' mode
101
Focus.configure({
102
mode: 'all',
103
className: 'has-focus'
104
})
105
```
106
107
### Focus Mode: Deepest
108
109
Marks only the deepest (innermost) node in the selection as focused.
110
111
```typescript
112
// Configuration for 'deepest' mode
113
Focus.configure({
114
mode: 'deepest',
115
className: 'has-focus'
116
})
117
```
118
119
### Focus Mode: Shallowest
120
121
Marks only the shallowest (outermost) node in the selection as focused.
122
123
```typescript
124
// Configuration for 'shallowest' mode
125
Focus.configure({
126
mode: 'shallowest',
127
className: 'has-focus'
128
})
129
```
130
131
## Types
132
133
```typescript { .api }
134
/**
135
* Configuration options for the Focus extension
136
*/
137
interface FocusOptions {
138
/**
139
* The CSS class name that should be added to the focused node
140
* @default 'has-focus'
141
* @example 'is-focused'
142
*/
143
className: string;
144
145
/**
146
* The mode by which the focused node is determined
147
* - 'all': All nodes in the selection path are marked as focused
148
* - 'deepest': Only the innermost node is marked as focused
149
* - 'shallowest': Only the outermost node is marked as focused
150
* @default 'all'
151
*/
152
mode: 'all' | 'deepest' | 'shallowest';
153
}
154
```
155
156
## Usage Examples
157
158
### Custom CSS Class
159
160
```typescript
161
import { Editor } from "@tiptap/core";
162
import { Focus } from "@tiptap/extensions";
163
164
const editor = new Editor({
165
extensions: [
166
Focus.configure({
167
className: 'editor-focused-node'
168
})
169
],
170
content: '<p>Your content here</p>',
171
});
172
```
173
174
### Deepest Node Focus
175
176
```typescript
177
// Only highlight the innermost focused element
178
const editor = new Editor({
179
extensions: [
180
Focus.configure({
181
mode: 'deepest',
182
className: 'deeply-focused'
183
})
184
],
185
content: '<p>Your content here</p>',
186
});
187
```
188
189
### Accessibility Enhancement
190
191
```typescript
192
// Use ARIA-friendly class names for screen readers
193
const editor = new Editor({
194
extensions: [
195
Focus.configure({
196
className: 'aria-current-element',
197
mode: 'deepest'
198
})
199
],
200
content: '<p>Your content here</p>',
201
});
202
```
203
204
### CSS Styling
205
206
```css
207
/* Style focused nodes */
208
.has-focus {
209
outline: 2px solid #007acc;
210
outline-offset: 2px;
211
}
212
213
/* Different styles for different focus modes */
214
.deeply-focused {
215
background-color: rgba(0, 122, 204, 0.1);
216
border-radius: 4px;
217
}
218
219
.aria-current-element {
220
box-shadow: 0 0 0 2px #007acc;
221
}
222
```
223
224
## Integration Requirements
225
226
The Focus extension requires:
227
228
- **Tiptap Core**: `@tiptap/core` for base Extension class
229
- **ProseMirror State**: `@tiptap/pm/state` for Plugin and PluginKey
230
- **ProseMirror View**: `@tiptap/pm/view` for Decoration and DecorationSet
231
- **Editor Instance**: Must be used within a Tiptap Editor configuration
232
233
## Behavior Notes
234
235
- Focus indicators only appear when the editor is both editable and focused
236
- The extension automatically handles cursor movement and selection changes
237
- CSS classes are applied and removed dynamically as focus changes
238
- Performance is optimized through ProseMirror's decoration system
239
- Works with all standard Tiptap nodes and marks