content/docs/(plugins)/(functionality)/(combobox)/emoji.mdx
Emoji adds two insertion paths: a : trigger that opens an inline combobox, and a toolbar popover for browsing categories. The package owns emoji data, trigger behavior, index search, picker state, frequent emoji storage, and insertion. The registry owns the inline input element and toolbar picker UI.
: trigger powered by @platejs/combobox.emoji_input node.@emoji-mart/data.createEmojiNode.EmojiKit installs EmojiPlugin with @emoji-mart/data and renders EmojiInputPlugin with the registry inline combobox.
import { createPlateEditor } from 'platejs/react';
import { EmojiKit } from '@/components/editor/plugins/emoji-kit';
export const editor = createPlateEditor({
plugins: EmojiKit,
});
emoji-node debounces the search text, queries EmojiInlineIndexSearch, and inserts the selected emoji.
emoji-toolbar-button renders the Radix popover picker backed by useEmojiDropdownMenuState.
| Layer | Owner | What It Does |
|---|---|---|
@platejs/emoji | Package | Exports BaseEmojiPlugin, BaseEmojiInputPlugin, insertEmoji, emoji search libraries, settings, categories, and types. |
@platejs/emoji/react | Package | Exports EmojiPlugin, EmojiInputPlugin, picker hooks, and frequent emoji storage. |
@platejs/combobox | Package | Provides trigger detection and transient input cleanup for the : flow. |
@emoji-mart/data | Dependency | Provides the emoji dataset used by the registry kit. |
emoji-kit | Registry | Adds EmojiPlugin with emoji-mart data and EmojiInputPlugin.withComponent(EmojiInputElement). |
emoji-node | Registry UI | Renders inline emoji search with InlineCombobox. |
emoji-toolbar-button | Registry UI | Renders the toolbar popover, category grid, search bar, and preview. |
inline-combobox | Registry UI | Renders the inline trigger input and popover primitives. |
@platejs/markdown | Package | Deserializes emoji shortcodes such as :fire: to Unicode text. |
The emoji plugin is edit-only. It inserts text or your custom node, then the transient emoji_input disappears.
npm install @platejs/emoji @emoji-mart/data
Use @emoji-mart/data when you want the full emoji dataset instead of the package default library.
import emojiMartData from '@emoji-mart/data';
import { EmojiInputPlugin, EmojiPlugin } from '@platejs/emoji/react';
import { createPlateEditor } from 'platejs/react';
import { EmojiInputElement } from '@/components/ui/emoji-node';
export const editor = createPlateEditor({
plugins: [
EmojiPlugin.configure({
options: {
data: emojiMartData as any,
},
}),
EmojiInputPlugin.withComponent(EmojiInputElement),
],
});
Render EmojiToolbarButton in your toolbar when users should browse emoji without typing :.
import { EmojiToolbarButton } from '@/components/ui/emoji-toolbar-button';
export function FixedToolbarButtons() {
return <EmojiToolbarButton />;
}
The inline path is a combobox flow.
| Step | Source |
|---|---|
Type : | BaseEmojiPlugin trigger. |
Previous character must match /^\s?$/ | Start of block or whitespace by default. |
| Insert transient input | createComboboxInput creates { type: KEYS.emojiInput, children: [{ text: '' }] }. |
| Search emoji data | EmojiInputElement calls EmojiInlineIndexSearch.getInstance(data).search(query).get(). |
| Select a result | InlineComboboxItem removes the input and calls insertEmoji(editor, emoji). |
| Insert final content | insertEmoji calls createEmojiNode(emoji) and inserts that node. |
EmojiInputElement sets filter={false} because emoji search already returns filtered results. It also uses hideWhenNoValue, so the popover stays closed until the user types a search value after :.
By default, selecting an emoji inserts the first native skin as text.
EmojiPlugin.configure({
options: {
createEmojiNode: ({ skins }) => ({ text: skins[0].native }),
},
});
Use createEmojiNode when your app stores emoji as structured inline nodes instead of text.
EmojiPlugin.configure({
options: {
createEmojiNode: (emoji) => ({
children: [{ text: emoji.id }],
emojiId: emoji.id,
type: 'emoji-chip',
}),
},
});
EmojiToolbarButton calls useEmojiDropdownMenuState, then passes the picker state into EmojiPicker.
| Option | Default | Use |
|---|---|---|
closeOnSelect | true | Close the toolbar popover after insertion. |
settings | EmojiSettings | Configure categories, per-line count, button size, and frequent emoji behavior. |
settings.showFrequent.limit | Package setting | Limits the frequent emoji category. |
Frequent emoji counts are stored in window.localStorage through FrequentEmojiStorage. On the server, the storage class returns the default frequent set.
@platejs/markdown deserializes emoji shortcodes to Unicode text.
Launch :fire: soon
Serializing the resulting value writes the Unicode emoji:
Launch 🔥 soon
| API | Package | Use |
|---|---|---|
BaseEmojiPlugin | @platejs/emoji | Edit-only trigger plugin with default :, emoji data, input creation, and text insertion. |
BaseEmojiInputPlugin | @platejs/emoji | Edit-only inline void emoji_input plugin. |
EmojiPlugin | @platejs/emoji/react | React emoji plugin with nested EmojiInputPlugin. |
EmojiInputPlugin | @platejs/emoji/react | React input plugin for EmojiInputElement. |
insertEmoji(editor, emoji) | @platejs/emoji | Inserts createEmojiNode(emoji). |
EmojiInlineIndexSearch | @platejs/emoji | Inline search index used by emoji-node. |
useEmojiDropdownMenuState(options?) | @platejs/emoji/react | Builds toolbar popover state and picker state. |
useEmojiPicker(options) | @platejs/emoji/react | Handles search, category focus, preview, selection, and frequent emoji updates. |
FrequentEmojiStorage | @platejs/emoji/react | Reads and writes frequent emoji counts through localStorage. |