npm version CI npm bundle size TypeScript React Context7 Ask DeepWiki
A React component that enables Facebook/Twitter-style @mentions and tagging in textarea inputs with full TypeScript support.
- β Flexible Triggers - Use any character or pattern to trigger mentions (@, #, :, or custom)
- π¨ Tailwind v4 Ready - First-class support for Tailwind CSS v4 utility styling
- β‘ Async Data Loading - Load suggestions dynamically from APIs
- π Smart Suggestions - Real-time filtering and matching
- βΏ Accessible - Built with ARIA labels and keyboard navigation
- π― TypeScript First - Written in TypeScript with complete type definitions
- π§ͺ Well Tested - Comprehensive test suite with Testing Library
- π SSR Compatible - Works with Next.js and other SSR frameworks
- π± Mobile Friendly - Touch-optimized for mobile devices
# npm npm install react-mentions-ts --save # yarn yarn add react-mentions-ts # pnpm pnpm add react-mentions-ts
React Mentions TS uses peer dependencies for its styling helpers and React runtime. Ensure these are installed in your application (skip any you already have):
# npm npm install class-variance-authority clsx react react-dom tailwind-merge # yarn yarn add class-variance-authority clsx react react-dom tailwind-merge # pnpm pnpm add class-variance-authority clsx react react-dom tailwind-merge
Check package.json for the latest peer dependency version ranges.
import { useState } from 'react' import { MentionsInput, Mention } from 'react-mentions-ts' function MyComponent() { const [value, setValue] = useState('') return ( <MentionsInput value={value} onMentionsChange={({ value: nextValue }) => setValue(nextValue)}> <Mention trigger="@" data={users} renderSuggestion={(entry) => <div>{entry.display}</div>} /> <Mention trigger="#" data={tags} /> </MentionsInput> ) }
@import "tailwindcss"; (...) @import "react-mentions-ts/styles/tailwind.css";
MentionsInput is the main component that renders the textarea control. It accepts one or multiple Mention components as children. Each Mention component represents a data source for a specific class of mentionable objects:
- π₯ Users -
@usernamementions - π·οΈ Tags -
#hashtagmentions - π Templates -
{{variable}}mentions - π Emojis -
:emoji:mentions - β¨ Custom - Any pattern you need!
The MentionsInput component supports the following props:
| Prop name | Type | Default value | Description |
|---|---|---|---|
| value | string | '' |
The value containing markup for mentions |
| onChange | function (event) | undefined |
Standard React change event fired by the underlying input. Note: event.target.value may not reflect the final state if a mention is modified. Use onMentionsChange for the canonical values. |
| onMentionsChange | function ({ trigger, value, plainTextValue, mentions, previousValue }) | undefined |
Called when the mention markup changes; receives the updated markup value, plain text, active mentions, and the previous markup value |
| onKeyDown | function (event) | empty function | A callback that is invoked when the user presses a key in the mentions input |
| singleLine | boolean | false |
Renders a single line text input instead of a textarea, if set to true |
| onBlur | function (event) | undefined |
Invoked when the underlying input loses focus |
| onMentionBlur | function (event, clickedSuggestion) | undefined |
Receives an extra clickedSuggestion flag when focus left via the suggestions list |
| suggestionsPortalHost | DOM Element | undefined | Render suggestions into the DOM in the supplied host element. |
| inputRef | React ref | undefined | Accepts a React ref to forward to the underlying input element |
| suggestionsPlacement | 'auto' | 'above' | 'below' |
'below' |
Controls where the suggestion list renders relative to the caret ('auto' flips when space is limited) |
| a11ySuggestionsListLabel | string | '' |
This label would be exposed to screen readers when suggestion popup appears |
| customSuggestionsContainer | function(children) | empty function | Allows customizing the container of the suggestions |
| inputComponent | React component | undefined | Allows the use of a custom input component |
| suggestionsDisplay | 'overlay' | 'inline' |
'overlay' |
Choose between the traditional suggestions overlay and inline autocomplete hints |
| ignoreAccents | boolean | false |
Ignores any accents on letters during search if set to true |
| spellCheck | boolean | false |
Controls browser spell checking on the underlying input (disabled by default) |
| onSelect | function (event) | empty function | A callback that is invoked when the user selects a portion of the text in the input |
onMentionsChange receives an object with the following fields:
value: the latest markup string containing mentionsplainTextValue: the same content without mention markupmentions: the mention occurrences extracted from the new valuepreviousValue: the markup string before the changetrigger: metadata about what caused the change.trigger.typeis one of'input','paste','cut','mention-add', or'mention-remove', and, when available,trigger.nativeEventreferences the originating DOM event (optional; do not rely on its exact shape). Regular text edits (typing, Backspace/Delete) usetrigger.type: 'input'.
Each data source is configured using a Mention component, which has the following props:
| Prop name | Type | Default value | Description |
|---|---|---|---|
| trigger | RegExp or string | '@' |
Defines the char sequence upon which to trigger querying the data source |
| data | array or function (search, callback) | null |
An array of the mentionable data entries (objects with id & display keys, or a filtering function that returns an array based on a query parameter |
| renderSuggestion | function (entry, search, highlightedDisplay, index, focused) | null |
Allows customizing how mention suggestions are rendered (optional) |
| allowSpaceInQuery | boolean | false |
Permit spaces within the search query portion after the trigger (useful for multi-word names) |
| markup | string | MentionSerializer |
'@[__display__](__id__)' |
Template string for stored markup, or pass a MentionSerializer instance for full control |
| displayTransform | function (id, display) | returns display |
Accepts a function for customizing the string that is displayed for a mention |
| onAdd | function (id, display, startPos, endPos) | empty function | Callback invoked when a suggestion has been added (optional) |
| appendSpaceOnAdd | boolean | false |
Append a space when a suggestion has been added (optional) |
Need the legacy
markupcustomization? ImportcreateMarkupSerializerfromreact-mentionsand passmarkup={createMarkupSerializer(':__id__')}(or any other template) to keep markup/parse logic in sync without wiring a regex manually.
If a function is passed as the data prop, it receives the current search query and should return a promise that resolves with the list of suggestions.
type User = { id: string; display: string } const fetchUsers = async (query: string): Promise<User[]> => { const response = await fetch(`/api/users?search=${query}`) return response.json() } <Mention trigger="@" data={fetchUsers} />
React Mentions ships its markup with Tailwind utility classes. Consumers should have Tailwind configured in their application build so these classes compile to real CSS. If you do not use Tailwind you can still provide your own styles via className, CSS modules, or inline styles.
The components assume Tailwind is available in the consuming app. A minimal setup looks like:
// tailwind.config.js module.exports = { content: ['./src/**/*.{js,ts,jsx,tsx}'], theme: { extend: {} }, plugins: [], }
/* src/index.css (or your global stylesheet) */ @import "tailwindcss"; @import "react-mentions-ts/styles/tailwind.css";
The optional helper react-mentions-ts/styles/tailwind.css only declares an @source "../dist"; directive so Tailwind v4 can detect the library's utility classes inside node_modules/react-mentions-ts/dist. Including it keeps your Tailwind config clean and avoids adding explicit content globs for the package.
If you are still on Tailwind v3, add ./node_modules/react-mentions-ts/dist/**/*.{js,jsx,ts,tsx} to the content array instead of importing the helper file.
<MentionsInput style={customStyle}> <Mention style={mentionStyle} /> </MentionsInput>
When suggestionsDisplay="inline", override the inlineSuggestion style slot to customize the inline hint (the default demo style lives in demo/src/examples/defaultStyle.ts).
See demo/src/examples/defaultStyle.ts for examples.
Simply assign a className prop to MentionsInput. All DOM nodes will receive derived class names:
<MentionsInput className="mentions"> <Mention className="mentions__mention" /> </MentionsInput>
Due to React Mentions' internal cursor tracking, use @testing-library/user-event for realistic event simulation:
import { render } from '@testing-library/react' import userEvent from '@testing-library/user-event' test('mentions work correctly', async () => { const user = userEvent.setup() const { getByRole } = render(<MyMentionsComponent />) await user.type(getByRole('textbox'), '@john') // assertions... })
- Contributions are welcome! If you want to contribute, first of all: thank you! β€οΈ
- Please check out our Contributing Guide for guidelines about how to proceed.
- React Mentions is licensed under the BSD-3-Clause License.
This project is a TypeScript rewrite and modernization of the original react-mentions library.
Contributors to react-mentions-tsMade with contrib.rocks.