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/mentionUsage
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
With avatars
Single-line
Custom trigger
Controlled
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.
| Prop | Type | Default | |
|---|---|---|---|
RegExp | string | "@" | ||
function | String(key) | ||
Placement | "bottom start" | ||
ReactNode | function | — | ||
boolean | — | ||
boolean | — | ||
boolean | — | ||
TokenSegmentList<any> | — | ||
TokenSegmentList<any> | — | ||
function | — | ||
Last updated on 7/29/2026