Features
- Text Suggestions: Add suggestions as text marks with inline annotations
- Block Suggestions: Create suggestions for entire blocks of content
- State Tracking: Track suggestion state and user interactions
- Undo/Redo Support: Full undo/redo support for suggestion changes
- Discussion Integration: Works with discussion plugin for complete collaboration
Kit Usage
Installation
The fastest way to add suggestion functionality is with the SuggestionKit
, which includes pre-configured SuggestionPlugin
and related components along with their Plate UI components.
SuggestionLeaf
: Renders suggestion text marksBlockSuggestion
: Renders block-level suggestionsSuggestionLineBreak
: Handles line breaks in suggestions
Add Kit
import { createPlateEditor } from 'platejs/react';
import { SuggestionKit } from '@/components/editor/plugins/suggestion-kit';
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
...SuggestionKit,
],
});
Manual Usage
Installation
pnpm add @platejs/suggestion
Extend Suggestion Plugin
Create the suggestion plugin with extended configuration for state management:
import {
type ExtendConfig,
type Path,
isSlateEditor,
isSlateElement,
isSlateString,
} from 'platejs';
import {
type BaseSuggestionConfig,
BaseSuggestionPlugin,
} from '@platejs/suggestion';
import { createPlatePlugin, toTPlatePlugin } from 'platejs/react';
import { BlockSuggestion } from '@/components/ui/block-suggestion';
import { SuggestionLeaf } from '@/components/ui/suggestion-node';
export type SuggestionConfig = ExtendConfig<
BaseSuggestionConfig,
{
activeId: string | null;
hoverId: string | null;
uniquePathMap: Map<string, Path>;
}
>;
export const suggestionPlugin = toTPlatePlugin<SuggestionConfig>(
BaseSuggestionPlugin,
({ editor }) => ({
options: {
activeId: null,
currentUserId: 'alice', // Set your current user ID
hoverId: null,
uniquePathMap: new Map(),
},
render: {
node: SuggestionLeaf,
belowRootNodes: ({ api, element }) => {
if (!api.suggestion!.isBlockSuggestion(element)) {
return null;
}
return <BlockSuggestion element={element} />;
},
},
})
);
options.activeId
: Currently active suggestion ID for visual highlightingoptions.currentUserId
: ID of the current user creating suggestionsoptions.hoverId
: Currently hovered suggestion ID for hover effectsoptions.uniquePathMap
: Map tracking unique paths for suggestion resolutionrender.node
: AssignsSuggestionLeaf
to render suggestion text marksrender.belowRootNodes
: RendersBlockSuggestion
for block-level suggestions
Add Click Handler
Add click handling to manage active suggestion state:
export const suggestionPlugin = toTPlatePlugin<SuggestionConfig>(
BaseSuggestionPlugin,
({ editor }) => ({
handlers: {
// Unset active suggestion when clicking outside of suggestion
onClick: ({ api, event, setOption, type }) => {
let leaf = event.target as HTMLElement;
let isSet = false;
const unsetActiveSuggestion = () => {
setOption('activeId', null);
isSet = true;
};
if (!isSlateString(leaf)) unsetActiveSuggestion();
while (
leaf.parentElement &&
!isSlateElement(leaf.parentElement) &&
!isSlateEditor(leaf.parentElement)
) {
if (leaf.classList.contains(`slate-${type}`)) {
const suggestionEntry = api.suggestion!.node({ isText: true });
if (!suggestionEntry) {
unsetActiveSuggestion();
break;
}
const id = api.suggestion!.nodeId(suggestionEntry[0]);
setOption('activeId', id ?? null);
isSet = true;
break;
}
leaf = leaf.parentElement;
}
if (!isSet) unsetActiveSuggestion();
},
},
// ... previous options and render
})
);
The click handler tracks which suggestion is currently active:
- Detects suggestion clicks: Traverses DOM to find suggestion elements
- Sets active state: Updates
activeId
when clicking on suggestions - Clears state: Unsets
activeId
when clicking outside suggestions - Visual feedback: Enables hover/active styling in suggestion components
Add Plugins
import { createPlateEditor, createPlatePlugin } from 'platejs/react';
import { SuggestionLineBreak } from '@/components/ui/suggestion-node';
const suggestionLineBreakPlugin = createPlatePlugin({
key: 'suggestionLineBreak',
render: { belowNodes: SuggestionLineBreak as any },
});
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
suggestionPlugin,
suggestionLineBreakPlugin,
],
});
render.belowNodes
: RendersSuggestionLineBreak
below nodes to handle line break suggestions
Enable Suggestion Mode
Use the plugin's API to control suggestion mode:
import { useEditorRef, usePluginOption } from 'platejs/react';
function SuggestionToolbar() {
const editor = useEditorRef();
const isSuggesting = usePluginOption(suggestionPlugin, 'isSuggesting');
const toggleSuggesting = () => {
editor.setOption(suggestionPlugin, 'isSuggesting', !isSuggesting);
};
return (
<button onClick={toggleSuggesting}>
{isSuggesting ? 'Stop Suggesting' : 'Start Suggesting'}
</button>
);
}
Add Toolbar Button
You can add SuggestionToolbarButton
to your Toolbar to toggle suggestion mode in the editor.
Discussion Integration
The suggestion plugin works with the discussion plugin for complete collaboration:
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
discussionPlugin,
suggestionPlugin.configure({
options: {
currentUserId: 'alice',
},
}),
suggestionLineBreakPlugin,
],
});
Keyboard Shortcuts
Key | Description |
---|---|
Cmd + Shift + S | Add a suggestion on the selected text. |
Plate Plus
Plugins
SuggestionPlugin
Plugin for creating and managing text and block suggestions with state tracking and discussion integration.
API
api.suggestion.dataList
Gets suggestion data from a text node.
api.suggestion.isBlockSuggestion
Checks if a node is a block suggestion element.
api.suggestion.node
Gets a suggestion node entry.
api.suggestion.nodeId
Gets the ID of a suggestion from a node.
api.suggestion.nodes
Gets all suggestion node entries matching the options.
api.suggestion.suggestionData
Gets suggestion data from a node.
api.suggestion.withoutSuggestions
Temporarily disables suggestions while executing a function.
Types
TSuggestionText
Text nodes that can contain suggestions.
TSuggestionElement
Block elements that contain suggestion metadata.
TInlineSuggestionData
Data structure for inline text suggestions.
id string
Unique identifier for the suggestion.
userId string
ID of the user who created the suggestion.
createdAt number
Timestamp when the suggestion was created.
type 'insert' | 'remove' | 'update'
Type of suggestion operation.
newProperties optional object
For update suggestions, the new mark properties being suggested.
properties optional object
For update suggestions, the previous mark properties.
TSuggestionData
Data structure for block-level suggestions.
id string
Unique identifier for the suggestion.
userId string
ID of the user who created the suggestion.
createdAt number
Timestamp when the suggestion was created.
type 'insert' | 'remove'
Type of block suggestion operation.
isLineBreak optional boolean
Whether this suggestion represents a line break insertion.
On This Page
FeaturesKit UsageInstallationAdd KitManual UsageInstallationExtend Suggestion PluginAdd Click HandlerAdd PluginsEnable Suggestion ModeAdd Toolbar ButtonDiscussion IntegrationKeyboard ShortcutsPlate PlusPluginsSuggestionPlugin
APIapi.suggestion.dataList
api.suggestion.isBlockSuggestion
api.suggestion.node
api.suggestion.nodeId
api.suggestion.nodes
api.suggestion.suggestionData
api.suggestion.withoutSuggestions
TypesTSuggestionText
TSuggestionElement
TInlineSuggestionData
TSuggestionData