Skip to content

Mention component

The Mention compound component is composed from the useMention hook and renders a WAI-ARIA 1.2 combobox-with-listbox-popup. It ships zero styles.

The provider. Owns the input adapter, request lifecycles, and listbox state.

PropTypeDescription
triggersTriggerConfig[]Registered triggers. Memoize this array.
onChange(rawValue, plainText, mentions) => voidFires on every value change.
onSelect(item) => voidFires when a listbox item is accepted.
defaultKindstringNamespace prefix in inserted tokens (default "item").

Renders the <textarea> with role="combobox" and the full ARIA wiring.

PropTypeDescription
acceptOnTabbooleanWhether Tab on an open listbox accepts the highlight. Default true.
<textarea> propsAll standard textarea props are forwarded.

Conditionally rendered <div role="listbox">, positioned by Floating UI. We use <div> (not <ul>) because the explicit ARIA role overrides implicit element semantics — every screen reader treats <div role="listbox"> and <ul role="listbox"> identically, and <div> keeps the unstyled component free of default list styles.

PropTypeDescription
render(ctx) => ReactNodeRender-prop access to the full mention context (items, status, activeIndex, …).
childrenReactNodeStatic children, rendered when render is omitted.
classNamestringClass applied to the listbox element.

A <div role="option" tabIndex={-1}> with aria-selected wired to the active highlight. Options must NOT be focusable in the activedescendant pattern — the textarea owns focus and addresses options by id via aria-activedescendant. tabIndex={-1} makes options programmatically focusable (which axe wants) while keeping them out of the Tab sequence.

PropTypeDescription
indexnumberPosition in the current items list.
itemMentionItemThe item to insert when accepted.
childrenReactNodeVisible content for the option.
classNamestringClass applied to the option element.

Mention.Loading / Mention.Error / Mention.Empty

Section titled “Mention.Loading / Mention.Error / Mention.Empty”

Unstyled passthrough slots for the corresponding listbox states. Render them inside the Mention.Listbox render prop based on ctx.status and ctx.items.length. Each accepts children (defaults provided) and className. They render <div role="presentation" data-arm-state="…">, so the default theme can target them via the data-arm-state attribute without coupling consumers to a class name.

<Mention.Listbox render={(ctx) => (
<>
{ctx.status === 'loading' && <Mention.Loading />}
{ctx.status === 'error' && <Mention.Error />}
{ctx.status === 'idle' && ctx.items.length === 0 && <Mention.Empty />}
{ctx.items.map((item, i) => (
<Mention.Item key={item.id} index={i} item={item}>{item.display}</Mention.Item>
))}
</>
)} />
Mention.Root
└─ provides MentionContext
├─ Mention.Input (reads context, attaches keyboard model + ARIA wiring)
└─ Mention.Listbox
├─ Mention.Item (reads context.activeIndex, fires acceptItem on mousedown)
└─ Mention.Loading | Mention.Error | Mention.Empty (slot passthroughs)