# API reference

Components, hooks, and editor transactions.

Canonical: https://reactmention.com/docs/api-reference



## Root and channels [#root-and-channels]

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

| Prop            | Purpose                                                                                                                                       |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `items`         | Array of items, or `(query, signal) => Promise<readonly T[]>`.                                                                                |
| `getKey`        | Unique, stable string or number for each item.                                                                                                |
| `getLabel`      | Search label and default insertion label.                                                                                                     |
| `allowSpaces`   | Allow horizontal spaces in this channel’s query. Defaults to false; tabs, line breaks, and editor atoms still stop detection.                 |
| `filter`        | Optional synchronous `(item, query) => boolean` for arrays. Defaults to case-insensitive label substring matching; fetcher results bypass it. |
| `trigger`       | One non-whitespace UTF-16 character; defaults to `@`.                                                                                         |
| `getInsertText` | Optional `(item, meta) => string`. Defaults to trigger + label.                                                                               |
| `onSelect`      | Optional notification after successful insertion.                                                                                             |
| `debounceMs`    | Async 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 [#compound-components]

| Component         | Behavior                                                                                                                     |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `Mention.Input`   | Native textarea. Accepts standard event handlers, controlled values, refs, styles, and form attributes.                      |
| `Mention.Popover` | Listbox 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.Item`    | Option with a `value`, children, and normal div props.                                                                       |
| `Mention.Loading` | Renders while a request is pending.                                                                                          |
| `Mention.Empty`   | Renders 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 [#popover-positioning]

| Prop               | Behavior                                                                                                                                                                     |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `anchorRef`        | Optional `RefObject<HTMLElement \| null>` for an element such as the composer wrapper. An omitted or empty ref keeps caret anchoring.                                        |
| `placement`        | Preferred side and alignment: `top`, `right`, `bottom`, or `left`, optionally suffixed with `-start` or `-end`. Defaults to `bottom-start`; flips when space is constrained. |
| `matchAnchorWidth` | Match the reference width, capped by available viewport space. Defaults to false. Use with an element anchor for a full-width composer panel.                                |
| `maxHeight`        | Maximum height in pixels, also limited by available space. Defaults to 280.                                                                                                  |
| `container`        | Portal 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](/docs/ai-composer#suggestion-positioning) for the executable example. Mention retains collision handling and updates the position on relevant scrolling and resizing.

## Hooks [#hooks]

`useMention()` and `useMentionMulti()` expose:

| Member                              | Purpose                                                                                                                                                   |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `open`, `query`, `activeTrigger`    | Popup visibility, query, and visible channel. A failed search keeps its query but sets `open` to false and `activeTrigger` to null.                       |
| `items`, `status`                   | Current results and `idle / loading / success / error` status. Old requests never supply current results.                                                 |
| `highlightedIndex`                  | Active 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 [#editor-adapter]

```ts
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](/docs/rich-text).

## Detection utility [#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](/docs/recipes/i18n#name-matching) for an opt-in local filter.
