Skip to content

useMention hook

useMention wires together the input adapter, trigger detection, request lifecycles, and listbox state. The unstyled Mention.* compound component is a thin shell around this hook — drop the shell and you can render any surface you like.

function useMention<T extends MentionItem = MentionItem>(
options: UseMentionOptions<T>,
): UseMentionResult<T>;
FieldTypeDescription
adapterAdapter | nullObject that owns the input surface. Use createTextareaAdapter(el) for a real <textarea>.
triggersTriggerConfig[]Registered triggers.
onChange(raw, plain, mentions) => voidValue-change callback.
onSelect(item, trigger) => voidAccept callback.
defaultKindstringNamespace prefix for inserted tokens.
{
// Value
value, plainText, mentions,
// Trigger / listbox state
active, isOpen, status, items, hasMore, activeIndex,
// Actions
moveHighlight, setHighlight, accept, acceptItem, close, loadMore,
}
import { useMention, createTextareaAdapter } from '@accessible-react-mentions/core';
import { useEffect, useRef, useState } from 'react';
function MyMention() {
const ref = useRef<HTMLTextAreaElement>(null);
const [adapter, setAdapter] = useState(null);
useEffect(() => { if (ref.current) setAdapter(createTextareaAdapter(ref.current)); }, []);
const m = useMention({
adapter,
triggers: [{ char: '@', source: async (q) => myUsers(q) }],
});
return (
<>
<textarea ref={ref} />
{m.isOpen && (
<ul>
{m.items.map((item, i) => (
<li key={item.id} aria-selected={m.activeIndex === i}>
{item.display}
</li>
))}
</ul>
)}
</>
);
}

For a fully accessible version of this with keyboard handling, ARIA wiring, and live announcements, use the Mention component instead.