# Message actions

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

Message actions are what a user can do with one message: react to it, reply to it, quote it, pin it, edit it, delete it and more. This page lists the actions the SDK ships, what each one does and who sees it. To add, remove or replace actions, see [Actions](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/actions/).

## What users get

When a user points at a message or moves focus into it, buttons appear beside it: one to add a reaction, one to reply in a thread, and a "more" button that opens the message menu.

Say the user opens the menu on a message from Bob. They see Add reaction, Thread Reply, Quote Reply, Pin, Copy Message, Mark as unread, Remind me, Save for later, Flag, Mute and Block User. On their own message they see Edit Message and Delete message instead of Mark as unread, Flag, Mute and Block User. Most actions confirm the result with a notification, such as "Message pinned" or "Saved for later".

## How it works across the layers

`MessageUI` renders `MessageActions` on every message that isn't deleted. `MessageActions` takes an action set, `defaultMessageActionSet` unless you pass another one. Each item in the set has three fields:

- `type` names the action, for example `pin`;
- `placement` puts it next to the message (`quick`) or in the menu (`dropdown`); one item with the placement `quick-dropdown-toggle` is the "more" button;
- `Component` renders it.

Before rendering, `useBaseMessageActionSetFilter` drops the actions the user can't take on this message. The remaining quick actions render beside the message, and the dropdown actions render in the menu.

Each action calls the state layer. The table lists the default set in menu order, with what each action calls and when the filter keeps it. "Own" means the connected user sent the message, and names in code font such as `send-reaction` are channel capabilities.

| Action                                | `type`            | What it calls                                                            | Shown when                                                                                         |
| ------------------------------------- | ----------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| Add reaction (quick and in the menu)  | `react`           | Opens the reaction selector                                              | `send-reaction`                                                                                    |
| Reply (quick), Thread Reply (menu)    | `reply`           | Opens the message's thread through `useWorkspaceNavigation().openThread` | `send-reply`, and the message isn't a thread reply                                                 |
| Quote Reply                           | `quote`           | `MessageComposer.setQuotedMessage(message)`                              | `quote-message`                                                                                    |
| Download Attachment                   | `download`        | Downloads the file, or opens a submenu when there are several            | The message has a file, image, video, audio or voice recording                                     |
| Pin, Unpin                            | `pin`             | `client.pinMessage(message)`, `client.unpinMessage(message)`             | The message isn't a thread reply                                                                   |
| Copy Message                          | `copyMessageText` | Copies `message.text` to the clipboard                                   | The message has text                                                                               |
| Resend                                | `resendMessage`   | `MessageOperations.retry`                                                | The message failed to send and can be retried, and `send-message`                                  |
| Edit Message                          | `edit`            | Loads the message into the composer                                      | `update-any-message`, or `update-own-message` on an own message; never a poll or a Giphy           |
| Mark as unread                        | `markUnread`      | `Channel.markUnread({ message_id })`                                     | Not own, `read-events`, and the message isn't a thread reply                                       |
| Remind me, Remove reminder            | `remindMe`        | `client.reminders.upsertReminder`, `client.reminders.deleteReminder`     | Reminders are on for the channel, and the message isn't saved for later                            |
| Save for later, Remove save for later | `saveForLater`    | `client.reminders.createReminder`, `client.reminders.deleteReminder`     | Reminders are on for the channel, and the message has no scheduled reminder                        |
| Flag                                  | `flag`            | `client.moderation.flagMessage({ message_id: message.id })`              | Not own, and `flag-message`                                                                        |
| Mute, Unmute                          | `mute`            | `client.moderation.mute` or `client.moderation.unmute` for the author    | Not own, and `mute-channel`                                                                        |
| Delete message                        | `delete`          | Asks to confirm, then `MessageOperations.delete`                         | `delete-any-message`, or `delete-own-message` on an own message; the message isn't deleted already |
| Block User, Unblock                   | `blockUser`       | `client.blockUser`, `client.unblockUser` for the author                  | Not own                                                                                            |

Some messages get no actions at all: a message that is still sending, a system or ephemeral message, and a bounced message. A message that failed to send keeps at most Resend, Edit Message and Delete message, and it keeps Edit Message and Delete message only when the failure was a network error.

A few things the table implies:

- **Updates on screen.** Reactions, deletes and resends change the message list before the server answers. Pinning doesn't at the state layer, but the Pin action updates the message on screen at once and puts it back if the request fails. [What's optimistic and what isn't](https://getstream.io/chat/docs/sdk/react/v15/state/writing-messages/whats-optimistic-and-what-isnt/) has the full list.
- **Notifications.** Pin, Mark as unread, the reminder actions, Flag, Mute and Delete report their result through `client.notifications`. See [Notifications](https://getstream.io/chat/docs/sdk/react/v15/features/app-experience/notifications/).
- **Layout.** Reply and Thread Reply open the thread through the layout. Without `ChatView`, or a `WorkspaceNavigationProvider` of your own, they do nothing. See [Moving between channels, threads and messages](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/moving-between-channels-threads-and-messages/).

Each action has its own feature page: [Reactions](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/reactions/), [Replies and threads](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/replies-and-threads/), [Quoted replies](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/quoted-replies/), [Pinned messages](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/pinned-messages/), [Sending, editing and deleting](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/sending-editing-and-deleting/), [Read state, unread and receipts](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/read-state-unread-and-receipts/), [Reminders and save for later](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/reminders-and-save-for-later/) and [Flagging, muting, blocking and bans](https://getstream.io/chat/docs/sdk/react/v15/features/moderation-and-safety/flagging-muting-blocking-and-bans/).

## Turning it on or off

Message actions are always on. Who sees which action depends on two things:

- **Capabilities.** The server gives the connected user a set of capabilities on each channel, derived from their roles and the channel type's permissions. The filter reads them for every message. Change them on the server, see [Permissions reference](https://getstream.io/chat/docs/javascript/permissions-reference/).
- **Channel settings.** Remind me and Save for later also need `channel.config.userMessageReminders.enabled`, see [Reminders and save for later](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/reminders-and-save-for-later/#turning-it-on-or-off).

The filter doesn't check a capability for Pin, Download or Block User. Pin shows even for users without the `pin-message` capability, and the server rejects their request. [Pinned messages](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/pinned-messages/#turning-it-on-or-off) shows how to hide it from them.

To remove the actions from every message, replace `MessageActions` with a component that renders nothing:

```tsx
import type { Channel as ChannelType } from "stream-chat";
import { Channel, WithComponents } from "stream-chat-react";

const NoMessageActions = () => null;

export const ChannelWithoutActions = ({
  channel,
}: {
  channel: ChannelType;
}) => (
  <WithComponents overrides={{ MessageActions: NoMessageActions }}>
    <Channel channel={channel}>{/* MessageList, MessageComposer */}</Channel>
  </WithComponents>
);
```

## Customizing

To change the actions, pass your own action set to `MessageActions` and register the wrapper with `WithComponents`. Start from `defaultMessageActionSet` to keep the built-in actions. The base filter runs on your set too, so the actions you keep stay hidden from users who can't take them.

This example removes Block User and keeps everything else:

```tsx
import type { Channel as ChannelType } from "stream-chat";
import {
  Channel,
  MessageActions,
  WithComponents,
  defaultMessageActionSet,
} from "stream-chat-react";

// Keep the "more" button, which has no type, and every action except blocking.
const messageActionSet = defaultMessageActionSet.filter(
  (action) =>
    action.placement === "quick-dropdown-toggle" || action.type !== "blockUser",
);

const CustomMessageActions = () => (
  <MessageActions messageActionSet={messageActionSet} />
);

export const ChannelWithCustomActions = ({
  channel,
}: {
  channel: ChannelType;
}) => (
  <WithComponents overrides={{ MessageActions: CustomMessageActions }}>
    <Channel channel={channel}>{/* MessageList, MessageComposer */}</Channel>
  </WithComponents>
);
```

[Actions](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/actions/) explains how action sets work and how to add quick and dropdown actions of your own. [Custom message actions](https://getstream.io/chat/docs/sdk/react/v15/recipes/message/custom-message-actions/) walks through a complete example. [Message translation](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/message-translation/#customizing) adds a Translate action.

## Reference

- [Message UI components](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message/message-ui-components/): the `MessageActions` props, `messageActionSet` and `disableBaseMessageActionSetFilter`.
- [ComponentContext](https://getstream.io/chat/docs/sdk/react/v15/component-reference/channel/componentcontext/): the `MessageActions` override key.
- [Message hooks](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/message-hooks/): the handlers behind the actions, such as `usePinHandler` and `useMarkUnreadHandler`.
- [Actions](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/actions/): every action set in the SDK.

---

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