# Mentions

> **Info:** This is release candidate documentation for **Stream Chat React Native SDK v10**. For the latest stable version, see the [latest version (v9)](https://getstream.io/chat/docs/sdk/react-native/).

## What users get

Typing `@` in the composer suggests people and groups to mention. The sent message highlights each mention, and the server notifies the people it names.

- **Suggestions.** `@` opens a list above the composer with channel members, `@channel`, `@here`, roles and user groups, narrowed as the user types. When the channel's members are searched locally, common accents are ignored, so "rene" finds "Rene" spelled with an accent.
- **Inserting.** Tapping a suggestion inserts it into the text, for example `@Ben`. Deleting that text removes the mention.
- **Highlighting.** Mentions in sent messages are colored by kind, and can be pressed.

There are five kinds of mention:

| Kind         | Typed as   | Notifies                | Message field                                                    |
| ------------ | ---------- | ----------------------- | ---------------------------------------------------------------- |
| `user`       | `@<name>`  | one user                | `mentioned_users`                                                |
| `channel`    | `@channel` | everyone in the channel | `mentioned_channel`                                              |
| `here`       | `@here`    | members who are online  | `mentioned_here`                                                 |
| `role`       | `@<role>`  | users with that role    | `mentioned_roles`                                                |
| `user_group` | `@<group>` | members of a user group | `mentioned_group_ids` when sending, `mentioned_groups` when read |

## How it works across the layers

### State: the text composer

The user types "Thanks @be" in "Design":

1. The text composer runs its middleware on every change. The mentions middleware finds the `@be` before the cursor and asks `MentionsSearchSource` for suggestions.
2. The search source collects them:
- **Users.** When the channel has fewer than 100 members loaded, it searches its loaded members and watchers locally, by name and id. Otherwise it queries the channel's members by name. With `mentionAllAppUsers`, it queries all users of the app instead.
- **`@channel` and `@here`**, when "be" starts their name.
- **Roles** through `client.searchRoles()`, and **user groups** through `client.searchUserGroups()`, which is scoped to the channel's team. Both need at least one character after `@`.
3. The suggestions land in the text composer's state as `suggestions`, and the UI lists them.
4. The user picks Ben. The middleware replaces `@be` with `@Ben` and adds Ben to the text composer's `mentions`.
5. When they send, the composer writes each mention to the message field of its kind, from the table above.

Each kind other than `user` is offered only when the user has its capability in the channel (see [Turning it on or off](#turning-it-on-or-off)). The capabilities are checked on every search, so the suggestions follow when they change.

The middleware and the search source are explained on [Suggestions](https://getstream.io/chat/docs/sdk/react-native/v10/state/writing-messages/suggestions/).

### UI: suggestions and highlighting

`AutoCompleteSuggestionList` renders the list while the text composer has suggestions. `MessageList` renders it, above the composer:

- `AutoCompleteSuggestionHeader` titles the list.
- Each row is an `AutoCompleteSuggestionItem`, which calls `TextComposer.handleSelect()` when it's pressed. For `@`, the row renders `MentionSuggestionItem`, which picks `MentionUserItem`, `MentionBroadcastItem` (`@channel` and `@here`), `MentionRoleItem` or `MentionUserGroupItem` by the suggestion's `mentionType`.

In the message list, `renderText` finds each mention in the message's text by matching the names in its mention fields, case-insensitively. It renders the mention in its own color: one for users, one for `@channel` and `@here`, one for roles and one for user groups. Pressing a mention calls the message's press handler with the `textMention` emitter. By default that dismisses the keyboard, or, on a message that failed to send or bounced, opens the menu or the bounce alert. See [Reacting to presses](#reacting-to-presses).

## Turning it on or off

User mentions are always available. The other kinds need a capability in the channel:

| Kind         | Capability       | Permission in the dashboard |
| ------------ | ---------------- | --------------------------- |
| `channel`    | `notify-channel` | `NotifyChannel`             |
| `here`       | `notify-here`    | `NotifyHere`                |
| `role`       | `notify-role`    | `NotifyRole`                |
| `user_group` | `notify-group`   | `NotifyGroup`               |

Grant them in the [Stream Dashboard](https://getstream.io/signin/?product=chat) under **Chat Messaging**, **Roles & Permissions**: pick the role (for example `channel_member`) and the channel type (for example `messaging`), then turn on the permissions. Until the user has a capability, that kind doesn't appear in the suggestions.

Two kinds also need data on the server:

- **Roles** are the roles defined on the same **Roles & Permissions** page.
- **User groups** are named sets of users, mentioned as one with `@<group name>`. They don't depend on channel membership: a group can be mentioned in any channel where group mentions are allowed. Create and manage them with a server-side SDK; see the [User Groups API reference](https://getstream.io/chat/docs/javascript/user-groups/).

## Customizing

### Changing the search

Give the mentions middleware a search source with other options, in a composer setup function. This one suggests every user of the app, not only the channel's members:

```ts
import type { StreamChat, TextComposerMiddleware } from "stream-chat";
import { createMentionsMiddleware, MentionsSearchSource } from "stream-chat";

export const mentionAllAppUsers = (client: StreamChat) =>
  client.config.setSetupFunction("messageComposer", ({ composer }) => {
    const { channel, textComposer } = composer;
    const searchSource = new MentionsSearchSource(channel, {
      mentionAllAppUsers: true,
    });

    // Same id as the default mentions middleware, so it takes its place.
    textComposer.middlewareExecutor.replace([
      createMentionsMiddleware(channel, {
        searchSource,
      }) as TextComposerMiddleware,
    ]);

    return () => {
      textComposer.middlewareExecutor.replace([
        createMentionsMiddleware(channel) as TextComposerMiddleware,
      ]);
    };
  });
```

Other options of `MentionsSearchSource`:

- `transliterate` turns the typed text and the names into Latin script before they're compared, `(text: string) => string`, for example the default export of `@sindresorhus/transliterate`. It applies where the search source compares names itself: the local member search and `@channel` and `@here`. Queries to the server aren't transliterated.
- `memberFilters` replaces the default member query. `userFilters` adds conditions to the user query that `mentionAllAppUsers` makes.
- `memberSort` and `userSort` replace the default order.

There is one setup function per kind, so this one replaces any other `messageComposer` setup function, such as one that calls `setupCommandUIMiddlewares`. Do all composer setup in one function. See [Suggestions](https://getstream.io/chat/docs/sdk/react-native/v10/state/writing-messages/suggestions/).

### Replacing a suggestion row

`MentionSuggestionItem` is an override key. It receives the suggestion as props. This one replaces the user rows and keeps the default for the other kinds:

```tsx
import { Text, View } from "react-native";
import type { MentionSuggestion } from "stream-chat";
import {
  MentionSuggestionItem,
  WithComponents,
} from "stream-chat-react-native";

const MentionRow = (item: MentionSuggestion) => {
  if (item.mentionType !== "user") return <MentionSuggestionItem {...item} />;

  return (
    <View style={{ paddingHorizontal: 16, paddingVertical: 8 }}>
      <Text>@{item.name ?? item.id}</Text>
    </View>
  );
};

export const App = () => (
  <WithComponents overrides={{ MentionSuggestionItem: MentionRow }}>
    {/* the rest of the app */}
  </WithComponents>
);
```

`AutoCompleteSuggestionList`, `AutoCompleteSuggestionHeader` and `AutoCompleteSuggestionItem` are override keys too, and replace the list for every trigger. The [Custom suggestions](https://getstream.io/chat/docs/sdk/react-native/v10/ui-cookbook/composer/custom-suggestions/) UI cookbook builds complete rows.

### Styling mentions

A mention's color comes from the semantic color tokens `chatTextMentionUser`, `chatTextMentionBroadcast`, `chatTextMentionRole` and `chatTextMentionGroup`. The rest of its style, such as the font weight, comes from `mentions` in `messageItemView.content.markdown` of the theme. See [Theming](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/theming/).

### Reacting to presses

`onPressMessage` and `onLongPressMessage` on `Channel` and `Thread` receive a press on a mention with the `textMention` emitter. `additionalInfo.mentionedEntity` is the mention, with its `mentionType`, and `additionalInfo.user` is the user for a user mention:

```tsx
import type { Channel as StreamChannel } from "stream-chat";
import {
  Channel,
  MessageComposer,
  MessageList,
} from "stream-chat-react-native";

export const ChannelWithMentionPresses = ({
  channel,
  openProfile,
}: {
  channel: StreamChannel;
  openProfile: (userId: string) => void;
}) => (
  <Channel
    channel={channel}
    onPressMessage={({ additionalInfo, defaultHandler, emitter }) => {
      if (emitter === "textMention") {
        if (additionalInfo?.user) openProfile(additionalInfo.user.id);
        return;
      }
      defaultHandler?.();
    }}
  >
    <MessageList />
    <MessageComposer />
  </Channel>
);
```

## Reference

- State: [Suggestions](https://getstream.io/chat/docs/sdk/react-native/v10/state/writing-messages/suggestions/), [Composer middleware](https://getstream.io/chat/docs/sdk/react-native/v10/state/writing-messages/composer-middleware/) and the [MessageComposer API](https://getstream.io/chat/docs/sdk/react-native/v10/reference/state/messagecomposer-api/).
- UI: [Message composer UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/message-composer-ui/) and [Message list UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/message-list-ui/).
- Props: [Composer UI components](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-composer/composer-ui-components/), [Channel](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel/channel/) and [Message UI components](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/message-ui-components/).
- Hooks: [Composer hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/composer-hooks/) and [Message hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/message-hooks/).

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/features/messaging/mentions/](https://getstream.io/chat/docs/sdk/react-native/v10/features/messaging/mentions/).