使用 AI 工具包的样式建议
当 AI 对文档进行更改时,您可以在编辑器中将这些更改显示为建议。在本指南中,您将学习如何通过修改样式来自定义建议的外观,并在其中显示自定义元素(例如菜单)。
为建议添加 CSS 样式
当使用默认的 renderDecorations 函数时,会应用以下类名:
.tiptap-ai-suggestion:应用于被建议范围覆盖的内容。.tiptap-ai-suggestion--selected:当光标位于建议范围内时应用。.tiptap-ai-suggestion--change-group:当建议是多个更改组成的组而非单个更改时应用。.tiptap-ai-suggestion-sub-change:应用于更改组中的单个子更改。.tiptap-ai-suggestion-diff:应用于显示在建议范围旁边的差异部件。.tiptap-ai-suggestion-diff--selected:当光标位于建议范围内时,应用于差异部件。.tiptap-ai-suggestion-diff--change-group:当差异部件是多个更改组成的组而非单个更改时应用。.tiptap-ai-suggestion-diff-sub-change:应用于差异更改组中的单个子更改。
您可以使用上述类来样式化建议,或提供自定义的 renderDecorations 函数以完全控制 UI。
CSS 样式示例
我们提供示例 CSS 样式供您快速上手。
预览模式
在预览模式中使用这些样式,以便在更改插入文档之前预览它们。
/* 将删除文字高亮为红色 */
.tiptap-ai-suggestion,
.tiptap-ai-suggestion > * {
background-color: oklch(80.8% 0.114 19.571);
color: oklch(0.396 0.141 25.723);
}
/* 更改组的背景色较浅(子更改变为较强高亮) */
.tiptap-ai-suggestion.tiptap-ai-suggestion--change-group,
.tiptap-ai-suggestion.tiptap-ai-suggestion--change-group > *:not(.tiptap-ai-suggestion-sub-change) {
background-color: oklch(0.936 0.032 17.717);
}
/* 行内更改组内的子更改高亮 */
.tiptap-ai-suggestion-sub-change {
background-color: oklch(80.8% 0.114 19.571);
}
/* 将插入文字高亮为绿色 */
.tiptap-ai-suggestion-diff,
.tiptap-ai-suggestion-diff > * {
background-color: oklch(87.1% 0.15 154.449);
}
/* 差异更改组的背景色较浅(子更改变为较强高亮) */
.tiptap-ai-suggestion-diff.tiptap-ai-suggestion-diff--change-group,
.tiptap-ai-suggestion-diff.tiptap-ai-suggestion-diff--change-group
> *:not(.tiptap-ai-suggestion-diff-sub-change) {
background-color: oklch(0.962 0.044 156.743);
}
/* 替换差异部件内的子更改高亮 */
.tiptap-ai-suggestion-diff-sub-change {
background-color: oklch(87.1% 0.15 154.449);
}
/* 正确渲染表格行插入 */
.tiptap-ai-suggestion-diff:has(tr) {
display: contents;
}
.tiptap-ai-suggestion-diff:has(tr) td,
.tiptap-ai-suggestion-diff:has(tr) th {
background-color: oklch(87.1% 0.15 154.449);
}审阅模式 / 文档比较
在审阅模式中使用这些样式,用于在文档中插入后审阅更改。
显示由文档比较功能生成的建议时也使用这些样式。
/* 将插入文字高亮为绿色 */
.tiptap-ai-suggestion,
.tiptap-ai-suggestion > * {
background-color: oklch(87.1% 0.15 154.449);
}
/* 更改组的背景色较浅(子更改变为较强高亮) */
.tiptap-ai-suggestion.tiptap-ai-suggestion--change-group,
.tiptap-ai-suggestion.tiptap-ai-suggestion--change-group > *:not(.tiptap-ai-suggestion-sub-change) {
background-color: oklch(0.962 0.044 156.743);
}
/* 行内更改组内的子更改高亮 */
.tiptap-ai-suggestion-sub-change {
background-color: oklch(87.1% 0.15 154.449);
}
/* 将删除文字高亮为红色 */
.tiptap-ai-suggestion-diff,
.tiptap-ai-suggestion-diff > * {
background-color: oklch(80.8% 0.114 19.571);
color: oklch(0.396 0.141 25.723);
}
/* 差异更改组的背景色较浅(子更改变为较强高亮) */
.tiptap-ai-suggestion-diff.tiptap-ai-suggestion-diff--change-group,
.tiptap-ai-suggestion-diff.tiptap-ai-suggestion-diff--change-group
> *:not(.tiptap-ai-suggestion-diff-sub-change) {
background-color: oklch(0.936 0.032 17.717);
}
/* 替换差异部件内的子更改高亮 */
.tiptap-ai-suggestion-diff-sub-change {
background-color: oklch(80.8% 0.114 19.571);
}
/* 正确渲染表格行删除 */
.tiptap-ai-suggestion-diff:has(tr) {
display: contents;
}
.tiptap-ai-suggestion-diff:has(tr) td,
.tiptap-ai-suggestion-diff:has(tr) th {
background-color: oklch(80.8% 0.114 19.571);
}在建议预览中将自定义节点视图设为只读
当建议预览渲染自定义节点视图时,这些节点视图会接收到标记它们属于 AI 工具包建议的装饰。使用 isAiToolkitSuggestionNodeView 来检测该状态,并禁用节点视图中的编辑控件。
import { NodeViewWrapper } from '@tiptap/react'
import { isAiToolkitSuggestionNodeView } from '@tiptap-pro/ai-toolkit'
function MathBlockNodeView({ decorations }) {
const isAiToolkitSuggestion = isAiToolkitSuggestionNodeView(decorations)
return (
<NodeViewWrapper contentEditable={!isAiToolkitSuggestion}>
{!isAiToolkitSuggestion ? <button>Edit equation</button> : null}
{/* 在此处渲染节点视图内容。 */}
</NodeViewWrapper>
)
}在建议中渲染 React 组件
您可以使用 renderDecorations 选项,结合React 门户,在建议内显示 React 组件。
首先,定义一个 React 组件并用 hook 存储 React 门户的挂载 HTML 元素。
import { useState } from 'react'
function MyComponent() {
const [portalElement, setPortalElement] = useState<HTMLElement | null>(null)
return null
}然后,在 displayOptions.renderDecorations 选项里,创建一个带有 HTML 元素的小部件装饰,用作 React 门户的入口点。
const aiToolkit = getAiToolkit(editor)
// AI 工具包中生成建议的示例方法
aiToolkit.executeTool({
reviewOptions: {
mode: 'preview',
displayOptions: {
renderDecorations({ suggestion, defaultRenderDecorations }) {
const decorations = defaultRenderDecorations()
decorations.push(
Decoration.widget(suggestion.range.to, () => {
const element = document.createElement('span')
setPortalElement(element)
return element
}),
)
return decorations
},
},
},
})最后,在 React 组件内,将任意 React 元素渲染到该门户内。
import { useState } from 'react'
import { createPortal } from 'react-dom'
function MyComponent() {
const [portalElement, setPortalElement] = useState<HTMLElement | null>(null)
if (portalElement) {
return <>{createPortal(<div>Hello, world!</div>, portalElement)}</>
}
return null
}选中建议时显示弹出框或提示框
您可以使用上述技术,在选中建议时显示提示框。
若要在选中建议时显示弹出框,需要使用 getCustomSuggestionDecoration 选项。此函数允许您向建议中添加自定义元素,包括弹出框。
下面是使用 React UI 库实现的简化示例。
import { useState } from 'react'
import { createPortal } from 'react-dom'
// 在 React 组件内部
function MyComponent() {
const toolkit = getAiToolkit(editor)
// 首先,定义 hook 存储弹出框挂载的 HTML 元素
const [popoverElement, setPopoverElement] = useState<HTMLElement | null>(null)
// 工具执行时,配置装饰的渲染方式
aiToolkit.executeTool({
reviewOptions: {
mode: 'preview',
displayOptions: {
renderDecorations({ suggestion, defaultRenderDecorations }) {
const decorations = defaultRenderDecorations()
// 创建包含 HTML 元素的 Prosemirror 装饰
decorations.push(
Decoration.widget(suggestion.range.to, () => {
const element = document.createElement('span')
setPopoverElement(element)
return element
}),
)
return decorations
},
},
},
})
const selectedSuggestion = toolkit.getSelectedSuggestion()
if (popoverElement && selectedSuggestion) {
// 将内容添加到自定义元素中。本例使用 React 门户渲染弹出框。
return <>{createPortal(<Popover suggestion={selectedSuggestion} />, popoverElement)}</>
}
return null
}我们推荐使用 Floating UI 库来显示弹出框。
在弹出框中渲染建议时,可以使用 getNextWord 和 getPreviousWord 工具函数,显示建议所在句子的前后单词。
import { getNextWord, getPreviousWord } from '@tiptap-pro/ai-toolkit'
// 获取句子中的前一个单词。
const { previousWord } = getPreviousWord(editor, suggestion.range.from)
// 获取句子中的后一个单词及其后面的标点符号(如果为句尾)。
const { nextWord, punctuationMark } = getNextWord(editor, suggestion.range.to)在编辑器外的侧边栏中显示建议
您可以通过 AI 工具包的 getSuggestions 方法获取当前建议。
const toolkit = getAiToolkit(editor)
const suggestions = toolkit.getSuggestions()然后,您可以使用这些数据在 UI 中(编辑器外)渲染建议。以下是使用 React UI 库实现的示例:
// 从 AI 工具包获取建议
const toolkit = getAiToolkit(editor)
const suggestions = toolkit.getSuggestions()
// 在 UI 中渲染建议
return (
<div>
{suggestions.map((suggestion) => (
<div key={suggestion.id}>
<p>删除内容: {toolkit.getTextRange(suggestion.range)}</p>
<p>添加内容: {suggestion.replacementOptions[0].content.toString()}</p>
</div>
))}
</div>
)后续步骤
- 在API 参考中了解更多有关建议的信息。请查看
displayOptions参数以了解所有自定义选项。