API reference

Components, hooks, and editor transactions.

Markdown Source

Root and channels

Mention.Root<T> and useMention<T>() accept:

PropPurpose
itemsArray of items, or (query, signal) => Promise<readonly T[]>.
getKeyUnique, stable string or number for each item.
getLabelSearch label and default insertion label.
allowSpacesAllow horizontal spaces in this channel’s query. Defaults to false; tabs, line breaks, and editor atoms still stop detection.
filterOptional synchronous (item, query) => boolean for arrays. Defaults to case-insensitive label substring matching; fetcher results bypass it.
triggerOne non-whitespace UTF-16 character; defaults to @.
getInsertTextOptional (item, meta) => string. Defaults to trigger + label.
onSelectOptional notification after successful insertion.
debounceMsAsync request delay, default 150 ms. Use 0 for immediate requests.

A separating space is appended when neither the insertion nor the following text already supplies whitespace.

For multiple channels, Root and useMentionMulti<M>() accept a triggers map instead of a single channel. Each channel has items, getKey, getLabel, and optional getInsertText, allowSpaces, and filter. The multi-channel onSelect payload is keyed by the active trigger, for example { "@": person }.

Root also accepts children, unstyled, and handleRef. The handle exposes open(), close(), commit(item), and host. Opening rescans the existing text at the caret and retries a failed query; it does not insert a trigger or duplicate a pending or successful request.

MentionSelectMeta contains trigger, query, and triggerOffset. Offsets use UTF-16 within the adapter's current text region.

Compound components

ComponentBehavior
Mention.InputNative textarea. Accepts standard event handlers, controlled values, refs, styles, and form attributes.
Mention.PopoverListbox anchored to the caret by default, hidden after a failed search. Accepts div props and the positioning options below.
Mention.List<T>Calls its child function for each result. Optional trigger restricts the active channel.
Mention.ItemOption with a value, children, and normal div props.
Mention.LoadingRenders while a request is pending.
Mention.EmptyRenders only after a successful query with no results.

React context cannot infer a List's item type from Root. Supply Mention.List<Person> and ensure that its type matches the selected channel. The same responsibility applies to useMentionContext<Person>().

Popover positioning

PropBehavior
anchorRefOptional RefObject<HTMLElement | null> for an element such as the composer wrapper. An omitted or empty ref keeps caret anchoring.
placementPreferred side and alignment: top, right, bottom, or left, optionally suffixed with -start or -end. Defaults to bottom-start; flips when space is constrained.
matchAnchorWidthMatch the reference width, capped by available viewport space. Defaults to false. Use with an element anchor for a full-width composer panel.
maxHeightMaximum height in pixels, also limited by available space. Defaults to 280.
containerPortal destination. Defaults to the editor document's body; null renders in place. This does not select the anchor.

For a panel above the whole composer, attach a useRef<HTMLDivElement>(null) to its wrapper and pass it as anchorRef, with placement="top-start" and matchAnchorWidth. See the AI composer for the executable example. Mention retains collision handling and updates the position on relevant scrolling and resizing.

Hooks

useMention() and useMentionMulti() expose:

MemberPurpose
open, query, activeTriggerPopup visibility, query, and visible channel. A failed search keeps its query but sets open to false and activeTrigger to null.
items, statusCurrent results and idle / loading / success / error status. Old requests never supply current results.
highlightedIndexActive option index, or -1.
getInputProps(props?)Composes textarea props and registers the built-in adapter through its ref. Pass handlers into this method rather than overwriting its returned handlers.
getEditorProps()ARIA attributes for a host with its own event system.
getPopoverProps()Listbox attributes.
getItemProps(item, index, props?)Option attributes and composed pointer handlers. Supply React keys separately.
setOpen(boolean)Dismiss or rescan the current selection. Opening a failed search starts a new request for that query.
commit(item)Returns false if the item, text, or selection is no longer current.
editor, setEditor(adapter)Current host and registration. Clear on cleanup.
refresh()Rescan after an editor transaction or selection change.
handleKeyDown(event)Returns true when handled. Call before editor key bindings.

useMentionContext<T>() returns this interface inside Root. For standalone hooks, render the popup with the returned props. A hook's popup styling and positioning are application-owned.

Values belong on the textarea's standard value and onChange props. There is no second value state on the mention hook.

Editor adapter

interface EditorSnapshot {
  text: string;
  caret: number;
  key?: unknown;
}

interface MentionEdit {
  from: number;
  to: number;
  text: string;
}

interface EditorAdapter<T> {
  element: HTMLElement;
  read(): EditorSnapshot | null;
  getCaretRect(): DOMRect | null;
  replace(edit: MentionEdit, item: T, meta: MentionSelectMeta): void | boolean;
}

Return null when editing is unavailable, a selection spans a range, or composition is active. Keep offsets consistent within one editable region. Use key to distinguish regions with identical text. Replacements must use the host's transaction system; return false if the operation is rejected.

See the working editor integration.

Detection utility

findActiveMention(value, caret, trigger = "@", { allowSpaces: false }) returns { trigger, query } or null. The trigger can also be an array of characters. It scans backwards from the caret and suppresses mid-word triggers, with soft boundaries for selected Unicode scripts.

Pass { allowSpaces: true } to allow Unicode horizontal space separators (Zs) in the query. Tabs, line breaks, and U+FFFC editor atoms always stop the scan. See name matching for an opt-in local filter.