Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion src/content/ai/ai-toolkit/agents/streaming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ See the [REST API reference](/ai/ai-toolkit/api-reference/rest-api#stream-a-tool
Install these dependencies in your client app:

```bash
npm install @ai-sdk/react @tiptap/extension-collaboration @tiptap/react @tiptap/starter-kit @tiptap-pro/provider @tiptap/ai-toolkit ai yjs
npm install @ai-sdk/react @tiptap/extension-collaboration @tiptap/react @tiptap/starter-kit @tiptap-pro/provider @tiptap/ai-toolkit @tiptap/y-tiptap ai yjs
```

</details>
Expand Down Expand Up @@ -230,6 +230,63 @@ const { messages, sendMessage, status } = useChat({
})
```

## Fade in text as it streams

Streamed text lands in the document token by token. The optional `AiInsertReveal` extension fades each run in as it arrives, so the edit reads as a smooth reveal instead of text popping in. It is a view-only decoration: it adds no marks and never touches the document, so it stays inert to accept/reject and to persistence, and a user's own typing is left untouched.

It builds on the client-side setup above: it reveals text that arrives through Collaboration, so it needs that setup. Import it from the `streaming-reveal` subpath and add it after `ServerAiToolkit`. It reads collaboration positions from `@tiptap/y-tiptap`, so install that too if it is not already a dependency.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

```tsx
import { ServerAiToolkit, getEditorContext } from '@tiptap/ai-toolkit'
import { AiInsertReveal } from '@tiptap/ai-toolkit/streaming-reveal'

const editor = useEditor({
immediatelyRender: false,
extensions: [
StarterKit.configure({ undoRedo: false }),
Collaboration.configure({ document: doc }),
ServerAiToolkit,
AiInsertReveal,
],
})
```

### CSS styles

The extension adds the `ai-insert-reveal` class to each freshly-streamed run and seeds its `animation-delay` so the fade resumes at the right point across the per-token re-render. It ships no CSS. Add an animation for that class to define the effect:

```css
.tiptap .ai-insert-reveal {
animation: ai-insert-reveal 380ms ease-out both;
}

@keyframes ai-insert-reveal {
from {
opacity: 0.35;
}
to {
opacity: 1;
}
}

@media (prefers-reduced-motion: reduce) {
.tiptap .ai-insert-reveal {
animation: none;
}
}
```

### Configuration

| Option | Default | Description |
| ------------ | -------------------- | --------------------------------------------------------------------------------------------------------------- |
| `className` | `'ai-insert-reveal'` | Class applied to each streamed run. Change it to run a different effect or to avoid a collision. |
| `durationMs` | `550` | How long each run keeps its decoration. Keep it at or above your CSS animation duration so the fade can finish. |

```ts
AiInsertReveal.configure({ durationMs: 700 })
```

## Stream as tracked changes

To let users review streamed edits instead of applying them directly, add `reviewOptions` to the `start` message. The edit then appears as a tracked-change suggestion that's typed into the document in real time and that users can accept or reject.
Expand Down
Loading