Headless Hook

Full control over rendering. You own the DOM, the library owns the logic.

When to Use

Minimal Example

import { useMentions } from "@skyastrall/mentions-react";

const users = [
  { id: "1", label: "Alice" },
  { id: "2", label: "Bob" },
];

function Editor() {
  const {
    editorRef, inputProps, listProps, getItemProps,
    isOpen, items, highlightedIndex, caretPosition, handleInput,
  } = useMentions({
    triggers: [{ char: "@", data: users }],
  });

  return (
    <div data-mentions="" style={{ position: "relative" }}>
      <div
        ref={editorRef}
        contentEditable="plaintext-only"
        onInput={handleInput}
        data-mentions-editor=""
        {...inputProps}
      />
      {isOpen && (
        <ul {...listProps} style={{
          position: "fixed",
          top: (caretPosition?.top ?? 0) + (caretPosition?.height ?? 0) + 4,
          left: caretPosition?.left ?? 0,
        }}>
          {items.map((item, i) => (
            <li key={item.id} {...getItemProps(i)}>
              {item.label}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

Important Attributes

Reading Values

const { markup, plainText, mentions } = useMentions({ triggers });

// markup: "@[Alice](1) hello"
// plainText: "@Alice hello"
// mentions: [{ id: "1", label: "Alice" }]

Programmatic Actions

const { focus, clear, insertTrigger } = useMentions({ triggers });

focus();              // Focus the editor
clear();              // Clear all content
insertTrigger("@");   // Insert @ and open dropdown