Mention

Mention lets users type a trigger character to insert people, commands, or other tokens inline as they write.

Comment
const people = /* ... */;

<Mention allowsNewlines className="w-[320px]">
  <Label>Comment</Label>
  <TokenInput />
  <Popover>
    <MenuContent items={people} renderEmptyState={() => "No people found."}>
      {(person) => (
        <MenuItem id={person.id} textValue={person.id}>
          <Avatar size="sm">
            <AvatarFallback>{person.name.charAt(0)}</AvatarFallback>
          </Avatar>
          <div className="flex flex-col">
            <span className="text-sm">{person.name}</span>
            <span className="text-xs text-fg-muted">@{person.id}</span>
          </div>
        </MenuItem>
      )}
    </MenuContent>
  </Popover>
</Mention>

Installation

npx shadcn@latest add @dotui/mention

Usage

Mention wires a mention experience onto the TokenField component: compose a TokenInput for the editable area plus a Popover + Menu for the suggestions, and Mention injects the wiring (value, caret-anchored popover, filtering, keyboard navigation, insertion) through context. Typing the trigger character (@ by default) opens the list at the caret and filters as you type; selecting an item inserts it as an inline token.

import { Mention } from '@/ui/mention'
import { MenuContent, MenuItem } from '@/ui/menu'
import { Popover } from '@/ui/popover'
import { TokenInput } from '@/ui/token-field'
<Mention allowsNewlines>
  <TokenInput aria-label="Comment" />
  <Popover>
    <MenuContent items={people}>
      {(person) => <MenuItem id={person.id}>{person.name}</MenuItem>}
    </MenuContent>
  </Popover>
</Mention>

Add a Label before the input when you want a visible label; otherwise give the input an aria-label. Without allowsNewlines the field stays single-line.

<Mention allowsNewlines>
  <Label>Comment</Label>
  <TokenInput />
  <Popover>{/* ...suggestions */}</Popover>
</Mention>

Anatomy

import { Mention } from '@/ui/mention'
import { MenuContent, MenuItem } from '@/ui/menu'
import { Popover } from '@/ui/popover'
import { TokenInput } from '@/ui/token-field'
<Mention>
  <TokenInput />
  <Popover>
    <MenuContent>
      <MenuItem />
    </MenuContent>
  </Popover>
</Mention>

Mention owns the value and caret-anchored popover, the TokenField's TokenInput renders the text and inline tokens, and the Popover + MenuContent render the suggestions. These are children, not props — there are no bespoke sub-components.

Value

The value is a TokenSegmentList — a list of plain-text and token segments. Use defaultValue for uncontrolled state, or value with onChange to control it; toString() joins the segments back into plain text, and each token segment carries the inserted item's key as its value.

const [value, setValue] = React.useState(
  () =>
    new TokenSegmentList([
      { type: 'text', text: 'Hey ' },
      { type: 'token', text: '@alexmiller' },
    ]),
)

<Mention value={value} onChange={setValue}>
  {/* ... */}
</Mention>

Triggers

The trigger prop changes the character that opens the list, and getItemText maps a selected item's key to the text inserted after the trigger.

<Mention trigger="#" getItemText={(key) => String(key)}>
  {/* ... */}
</Mention>

Pass a regular expression to support several triggers at once. Children may be a function receiving the active trigger and query, so the suggestions can depend on which trigger the user typed.

<Mention trigger={/[@/]/}>
  {({ trigger }) => (
    <>
      <TokenInput aria-label="Prompt" />
      <Popover>
        <MenuContent items={trigger === '/' ? commands : files}>
          {(item) => <MenuItem id={item.id}>{item.id}</MenuItem>}
        </MenuContent>
      </Popover>
    </>
  )}
</Mention>

Placement

Set placement to move the suggestions popover relative to the caret (default "bottom start").

Examples

Basic

Multiple triggers

/review the changes in @src/app.tsx

With avatars

Comment

Single-line

Custom trigger

Message

Controlled

Comment
Hey

Value: Hey

API Reference

Mention composes the TokenField's TokenInput for the editable area, and the Popover and Menu primitives for the suggestion list.

Mention

A mention input lets users type a trigger character (like `@` or `/`) to open an inline list of suggestions and insert one as an inline token. `Mention` wires the behaviour onto the [TokenField](/docs/components/token-field) component — a `TokenInput` for the editable area, a `Popover` + `Menu`/`MenuItem` for the suggestions — by injecting their props through context. The value is a `TokenSegmentList` of text and token segments.

PropType
RegExp | string
function
Placement
ReactNode | function
boolean
boolean
boolean
TokenSegmentList<any>
TokenSegmentList<any>
function

Last updated on 7/29/2026