# Quickstart

Add typed mention suggestions to a React textarea.

Canonical: https://reactmention.com/docs



Mention opens suggestions at the caret while someone writes. Start with a native textarea for plain text, or [connect a rich-text editor](/docs/rich-text) when your document needs mention nodes, formatting, or editor history.

## Install [#install]

Use an application with **React 19**, then install the package:

```sh title="Install Mention"
npm install @danielivanov/mention@^0.2.1
```

With Bun, use `bun add @danielivanov/mention@^0.2.1`. These examples require Mention 0.2.1. The stylesheet is optional; import it once for the default popup and option styles.

## Try the interaction [#try-the-interaction]

Type `@al` below to find Alice. Use ArrowDown and ArrowUp to navigate; Enter or Tab inserts the highlighted result. Escape dismisses suggestions without changing the message. Focus stays in the textarea, and Enter without an active suggestion adds a new line.

<div className="docs-example not-prose">
  <Composer />
</div>

Selecting Alice inserts plain text, `@Alice`, followed by a separating space when needed. Arrays are filtered by a case-insensitive substring match on `getLabel`.

## Add a composer [#add-a-composer]

This is the complete source of the example above. The rendered example and this code block use the same file.

In a Next.js App Router application, keep `"use client"` at the top: state, event handlers, and item render functions belong in a client component. Style the native label, hint, and textarea with your application's existing styles. The optional package stylesheet styles the suggestions.

```tsx title="Composer.tsx"
"use client";

import { Mention } from "@danielivanov/mention";
import { useId, useState } from "react";
import "@danielivanov/mention/styles.css";

type Person = { id: string; name: string };

const people: Person[] = [
  { id: "alice", name: "Alice" },
  { id: "bob", name: "Bob" },
  { id: "carol", name: "Carol" },
];

export function Composer() {
  const id = useId();
  const [message, setMessage] = useState("");

  return (
    <Mention.Root<Person>
      items={people}
      getKey={(person) => person.id}
      getLabel={(person) => person.name}
    >
      <label htmlFor={id}>Message</label>
      <p id={`${id}-hint`}>
        Type @ to find a person. Use the arrow keys to choose, Enter to insert,
        and Escape to dismiss.
      </p>
      <Mention.Input
        id={id}
        name="message"
        value={message}
        onChange={(event) => setMessage(event.currentTarget.value)}
        aria-describedby={`${id}-hint`}
        placeholder="Write a message…"
        rows={4}
      />
      <Mention.Popover container={null} aria-label="People">
        <Mention.List<Person>>
          {(person) => (
            <Mention.Item value={person}>{person.name}</Mention.Item>
          )}
        </Mention.List>
        <Mention.Empty>No people found. Try another name.</Mention.Empty>
      </Mention.Popover>
    </Mention.Root>
  );
}

```

`getKey` supplies each item's stable identity. `getLabel` supplies the local search label and default insertion label. Give `Mention.List` its item type explicitly: React context cannot infer that type from `Mention.Root`.

The input supports normal textarea props, including `value`, `onChange`, `onBlur`, `onKeyDown`, and `ref`. A consumer key handler runs first and can call `preventDefault()` to override Mention's handling. `onSelect` on Root is optional; use it only when you need a notification after insertion.

The example uses `container={null}` to keep the listbox within the article's landmark. Use a portal container when your application's clipping or layering requires one.

## Choose your next step [#choose-your-next-step]

* [Controlled forms](/docs/recipes/controlled-value): keep text in your form's existing state.
* [Async search](/docs/recipes/async-items): fetch suggestions with debouncing, cancellation, and status feedback.
* [Multiple triggers](/docs/recipes/multi-trigger): combine people, channels, or other item types in one host.
* [Styling](/docs/recipes/styling): use the optional stylesheet or your own design system.
* [Rich-text editors](/docs/rich-text): keep structured mentions and edits in an editor document.
* [API reference](/docs/api-reference): inspect component, hook, and adapter contracts.
* [Coding-agent guide](/docs/agents): hand an integration task to a coding agent.

## Verify in your application [#verify-in-your-application]

Check insertion, empty results, Escape, focus, and ordinary typing with your actual form state. Test the popup inside your dialogs and scrolling containers. For asynchronous data, also test requests resolving out of order.

Read [Accessibility](/docs/accessibility) for the native textbox and listbox relationship, keyboard behavior, and manual verification guidance. Automated checks do not establish screen-reader or real OS IME compatibility.
