AI Caret
The AiCaret extension displays a cursor decoration at the position where the AI is currently inserting content. It provides real-time visual feedback during streaming operations, similar to the Collaboration Caret extension.
Usage
Import the AiCaret extension from @tiptap-pro/ai-toolkit and add it to your editor extensions.
import { AiCaret, AiToolkit } from '@tiptap-pro/ai-toolkit'
const editor = useEditor({
extensions: [StarterKit, AiToolkit, AiCaret],
})The caret appears automatically during streaming operations like streamHtml, streamTool, and tiptapEditWorkflow. It disappears after the streaming finishes.
Configuration
You can configure the caret's timeout, user label, and rendering.
AiCaret.configure({
// How long the caret stays visible after the last update (ms)
timeout: 2000,
// User details for the caret label
user: {
name: 'AI',
color: '#a5b4fc',
},
})Options
| Option | Type | Default | Description |
|---|---|---|---|
timeout | number | 2000 | How long the caret stays visible after the last update (ms). |
user | { name: string, color: string } | { name: 'AI', color: '#a5b4fc' } | The name and color displayed on the caret label. |
render | (user: AiCaretUser) => HTMLElement | Built-in render function | Custom function to render the caret DOM element. |
CSS styles
The default render function creates a DOM element with the class tiptap-ai-caret and a label with the class tiptap-ai-caret__label. Add the following CSS to style the caret:
.tiptap .tiptap-ai-caret {
border-left: 1px solid #0d0d0d;
border-right: 1px solid #0d0d0d;
margin-left: -1px;
margin-right: -1px;
pointer-events: none;
position: relative;
word-break: normal;
}
.tiptap .tiptap-ai-caret__label {
border-radius: 3px 3px 3px 0;
color: #0d0d0d;
font-size: 12px;
font-style: normal;
font-weight: 600;
left: -1px;
line-height: normal;
padding: 0.1rem 0.3rem;
position: absolute;
top: -1.4em;
user-select: none;
white-space: nowrap;
}The border-color and background-color of the caret and label are set inline based on the user.color option.
Custom rendering
You can provide a custom render function to fully control the caret DOM element.
AiCaret.configure({
render: (user) => {
const el = document.createElement('span')
el.className = 'my-custom-ai-caret'
el.style.borderColor = user.color
el.textContent = user.name
return el
},
})Events
The AiCaret extension emits events through the Tiptap events API. You can subscribe to them to react to the caret's movement — for example, to follow the AI's writing position with custom UI behavior.
Available events
| Event | Description | Payload |
|---|---|---|
aiCaret:positionChanged | Fired whenever the AI caret position is updated during a streaming or edit operation. | { position: number } |
The position value is a ProseMirror document position pointing to where the AI caret is currently placed.
Subscribing to events
Use editor.on to listen for the event, and editor.off to unsubscribe when no longer needed.
editor.on('aiCaret:positionChanged', ({ position }) => {
console.log('AI caret moved to position', position)
})The aiCaret:positionChanged event can fire frequently during streaming — once per streamed chunk. If your handler performs expensive work, consider throttling it with requestAnimationFrame or a utility like lodash.throttle.