-
Notifications
You must be signed in to change notification settings - Fork 2
Mentions
The mentions addon provides a native, fixed-list @ flow. It detects a trigger while the user types, filters the configured suggestions, and shows them in the native toolbar area. A selected suggestion becomes a void mention node in the shared document handle.
Build a schema that contains the mention node before creating the handle. The addon configures the UI; it does not change a handle's schema after creation.
import { useEffect, useMemo, useRef } from 'react';
import { Button } from 'react-native';
import {
buildMentionFragmentJson,
createNativeEditorDocumentHandle,
createMentionsAddon,
defaultSchema,
RichTextEditor,
resolveDocumentDescriptor,
withMentionsSchema,
type MentionSuggestion,
type RichTextEditorRef,
} from '@apollohg/react-native-rich-text-editor';
const schema = withMentionsSchema(defaultSchema);
const descriptor = resolveDocumentDescriptor(schema);
const suggestions: readonly MentionSuggestion[] = [
{
key: 'ada',
title: 'Ada Lovelace',
label: '@ada',
attrs: { userId: 'user_42', kind: 'person' },
},
{
key: 'support',
title: 'Support team',
subtitle: 'Routes to the on-call queue',
attrs: { teamId: 'support', kind: 'team' },
},
];
export function MentionEditor() {
const editorRef = useRef<RichTextEditorRef>(null);
const documentHandle = useMemo(
() =>
createNativeEditorDocumentHandle({
initialization: { type: 'localEmpty' },
schema,
}),
[]
);
useEffect(() => () => documentHandle.destroy(), [documentHandle]);
function insertAda() {
editorRef.current?.insertContentJson(
buildMentionFragmentJson(
{
label: '@ada',
mentionSuggestionChar: '@',
userId: 'user_42',
kind: 'person',
},
descriptor
)
);
}
return (
<>
<RichTextEditor
ref={editorRef}
documentHandle={documentHandle}
addons={[createMentionsAddon({ trigger: '@', suggestions })]}
/>
<Button title="Mention Ada" onPress={insertAda} />
</>
);
}trigger is trimmed and defaults to "@". Each suggestion needs a stable key and a non-empty title; subtitle is secondary native UI text. A missing or blank label becomes the suggestion's title.
The addon first supplies label and mentionSuggestionChar: trigger, then merges suggestion.attrs. That means attrs deliberately wins if it supplies either key. Use attrs for durable application metadata such as an ID, entity kind, or tenant; those values are written into the mention node.
withMentionsSchema() appends the standard mention node unless a node of that name already exists. Its allowUndeclaredAttrs: true setting is intentional: it preserves application-defined metadata and mention fields such as mentionSuggestionChar and mentionTheme through JSON ingestion.
Use mentionNodeSpec() only when you need to inspect or extend the standard node definition. If you declare a mention node yourself, preserve its inline, void semantics and its undeclared-attribute policy; a narrow attrs map otherwise drops metadata that your app expects to round-trip. Schema Customization explains the common schema constraints.
buildMentionFragmentJson(attrs, descriptor, { trailingSpace: true }) optionally appends an unmarked space so typing can continue after the mention. Without that option, no space is appended. This is the matching helper for an editor ref's insertContentJson(). Pass the descriptor resolved from the same schema as the handle when the document-role node is not named doc; this keeps the fragment root compatible with the active schema.
Use createMentionsAddon({ theme }) for inline-node overrides and suggestion controls. theme.mention on the editor/viewer supplies base chip styling; the addon node theme overrides it, and persisted per-mention themes override supplied fields again. See Styling.
<RichTextEditor
documentHandle={documentHandle}
addons={[
createMentionsAddon({
suggestions,
theme: {
node: {
color: '#124e78',
backgroundColor: '#dcefff',
fontWeight: '700',
paddingHorizontal: 8,
paddingVertical: 3,
borderWidth: 1,
borderColor: '#8fc4e8',
borderRadius: 6,
},
suggestions: {
backgroundColor: '#ffffff',
option: {
textColor: '#152536',
highlightedBackgroundColor: '#c8e5fa',
highlightedTextColor: '#124e78',
},
},
},
}),
]}
/>EditorMentionTheme.node accepts inline typography, background, padding, and full border fields, including per-edge widths/colors and corner radii. Padding and borders render in both editor and viewer. Use color for node text; the old textColor alias remains accepted for persisted themes. suggestions.option styles each normal or highlighted row; its text field is still textColor. Suggestion container fields in suggestions apply to the React EditorToolbar, while native keyboard toolbars style rows only.
Use padding for all sides, paddingHorizontal / paddingVertical for an axis, or paddingTop, paddingRight, paddingBottom, and paddingLeft for individual edges. Specific edges win over axis shorthands, which win over padding. Values must be finite and nonnegative; padding: 0 removes all default chip padding. Omitted edges inherit from the base/addon theme, falling back to native defaults: horizontal 6 and vertical 4 on iOS, horizontal 4 and vertical 2 on Android. Set explicit values for matching insets across platforms. Borders add their widths separately. See EditorTheme Reference.
onQueryChange receives the current query, trigger, active range, and optional document version. Filter or fetch in application code and pass the current results back through suggestions. onSelect runs after a suggestion is inserted.
resolveSelectionAttrs runs immediately before insertion and may merge additional durable attributes over the suggestion attrs. resolveTheme runs after that merge; a valid returned EditorMentionTheme is stored as the node's mentionTheme attribute. A thrown callback or null result keeps the existing values, and an invalid theme is dropped instead of writing unrenderable content.
| Callback | Event / result |
|---|---|
onQueryChange |
query, trigger, range, isActive, optional documentVersion. |
resolveSelectionAttrs |
trigger, full suggestion, current attrs, active markAttrs, range, optional documentVersion; returns extra attrs or null. |
resolveTheme |
The resolved-selection event; returns an EditorMentionTheme or null. |
onSelect |
trigger, full suggestion, final persisted attrs, optional documentVersion. |
RichTextViewer automatically composes its schema with the standard mention node. Give its mention addon a display prefix and an onPress handler for application navigation.
import { createMentionsAddon, RichTextViewer } from '@apollohg/react-native-rich-text-editor';
<RichTextViewer
contentJSON={savedDocument}
addons={[
createMentionsAddon({
prefix: '@',
theme: {
node: { color: '#124e78', backgroundColor: '#dcefff' },
},
onPress: ({ docPos, label, attrs }) => {
openProfile({ docPos, label, userId: String(attrs.userId) });
},
}),
]}
/>;The press event contains the document position, the displayed label, and parsed node attributes. If the native attribute payload is not a JSON object, the viewer calls onError with code: "INVALID_MENTION_ATTRIBUTES" and does not call onPress. See Viewer for sizing and viewer error handling.
| Field | Use |
|---|---|
trigger?: string |
Trigger character or token; defaults to "@" after trimming. |
suggestions?: readonly MentionSuggestion[] |
Current list rendered and filtered natively; replace it from React state for dynamic results. |
theme?: EditorMentionTheme |
Base node and suggestion-list presentation. |
resolveSelectionAttrs / resolveTheme
|
Synchronous selection-time attribute and per-mention theme resolvers. |
onQueryChange / onSelect
|
Query lifecycle and post-insertion callbacks. |
The 2.x API uses a flat readonly addon array; duplicate mentions descriptors are rejected. Replace the descriptor when its suggestions or options change. See Addons.
For the type-level field definitions, see Types and Events Reference.
React Native Rich Text Editor · Documentation · Migration Guide