Mention
Mention is a text field (or textarea) that suggests options after a prefix such as @. Typing the prefix at the start or after a space opens a menu under it; the text between the prefix and the caret filters the options, and picking one inserts prefix + value + separator. It is built on Input, and shares its option list with Select. Focus stays in the field, which drives the list with aria-activedescendant: a text input is the combobox of the WAI-ARIA combobox pattern; a textarea stays a multiline textbox, since HTML doesn’t allow it the combobox role.
Demos
Basic
Type @ to open the menu at the @. A prefix inside a word (like an email address) doesn’t open it. Typing the separator (a space by default), moving the caret out of the mention, Escape or leaving the field closes it. Disabled options are skipped.
Textarea
type="textarea" uses a textarea; autosize and rows work as in Input. The menu opens under the line with the prefix, also after the textarea has scrolled. A line break ends a mention.
Several prefixes
prefix takes an array. onSearch and onSelect tell you which prefix was typed, so you can pass different options for each.
Async search
onSearch(pattern, prefix) is called whenever the mention being typed changes; fetch the options there. While loading, the menu shows a spinner.
Keyboard
While the menu is open: ↑ / ↓ move the active option (skipping disabled ones and wrapping); Enter or Tab inserts it; Escape closes the menu until you type again. Everything else edits the text. Enter and Tab are only taken when there is an option to insert; Mention handles keys before your onKeyDown, so check event.defaultPrevented there (for example before sending a message on Enter).
Props
| Name | Type | Default | Description | Version |
|---|---|---|---|---|
options | MentionMixedOption[] | required | Options { label, value, disabled? }, optionally in groups { type: "group", label, key, children }. value is what gets inserted. | Unreleased |
value | string | null | undefined | Controlled text. | Unreleased |
defaultValue | string | "" | Initial text when uncontrolled. | Unreleased |
onUpdateValue | (value: string) => void | undefined | Called with the new text on every edit and pick. | Unreleased |
prefix | string | string[] | "@" | What starts a mention. | Unreleased |
separator | string | " " | Inserted after a picked option; typing it ends a mention. | Unreleased |
type | text | textarea | text | A single-line input or a textarea. | Unreleased |
autosize / rows | Textarea sizing, as in Input. | Unreleased | ||
filter | (pattern, option) => boolean | label or value contains | Whether an option matches the typed pattern (case-insensitive by default). | Unreleased |
onSearch | (pattern: string, prefix: string) => void | undefined | Called when the mention being typed changes. | Unreleased |
onSelect | (option, prefix: string) => void | undefined | Called after an option is inserted. | Unreleased |
renderLabel | (option) => ReactNode | undefined | Custom label in the menu. | Unreleased |
loading | boolean | false | The menu shows a spinner instead of options. | Unreleased |
empty | ReactNode | locale “No data” | Shown when no option matches. | Unreleased |
placeholder | string | undefined | Shown when empty. | Unreleased |
size | tiny | small | medium | large | medium | Field height and text size. | Unreleased |
status | success | warning | error | undefined | Border color. | Unreleased |
disabled | boolean | false | Can’t be edited. | Unreleased |
placement | PopoverPlacement | bottom-start | Where the menu opens, relative to the prefix. | Unreleased |
to / zIndex | Same as Popover. | Unreleased | ||
onFocus / onBlur | (event) => void | undefined | Focus entering / leaving the field. | Unreleased |
Other Input props are forwarded: className, style and wrapperRef go to the bordered box; ref, id, aria-*, onKeyDown and other native attributes to the input or textarea. Mention’s prefix and loading replace Input’s affix and spinner.