# MessageActions

The toolbar a message shows on hover, focus or a tap: react, reply, forward, pin and select, then your own controls such as a More menu. React opens the quick reactions and the full EmojiPicker. Pass it to MessageBubble as toolbar.

**Dependencies:** npm: 1 direct, 6 total; registry: 6 direct, 7 total.

## Usage

### When to use

- Offer the actions on one message (react, reply, forward, pin, select) when the reader points at it, focuses it or taps it.
- Add a More menu with the rarer actions, such as Copy, Edit and Delete.

### When not to use

- Actions on many picked messages at once. Use MessageList selection with a bar of Buttons.
- A toolbar that is always shown above a document. Use ToggleGroup or Buttons in a row.
- A right-click menu on any item. Use ContextMenu.

## Examples

### Toolbar

```tsx
<MessageActions onReact={addReaction} onReply={replyToMessage} onForward={forwardMessage} onPinnedChange={setPinned} onSelect={startSelection} />
```

### Pinned message

Pin stays pressed, with a filled icon, while the message is pinned.

```tsx
<MessageActions pinned onReact={addReaction} onReply={replyToMessage} onPinnedChange={setPinned} />
```

### With a More menu

Your own controls follow the built-in ones.

```tsx
<MessageActions onReact={addReaction} onReply={replyToMessage}>
  <DropdownMenu>
    <DropdownMenuTrigger asChild>
      <Button size="sm" variant="ghost" iconOnly aria-label="More actions">
        <IconDots size={16} />
      </Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent align="end">
      <DropdownMenuItem leadingIcon={<IconCopy size={16} />}>Copy text</DropdownMenuItem>
      <DropdownMenuItem leadingIcon={<IconPencil size={16} />}>Edit</DropdownMenuItem>
      <DropdownMenuItem destructive leadingIcon={<IconTrash size={16} />}>Delete</DropdownMenuItem>
    </DropdownMenuContent>
  </DropdownMenu>
</MessageActions>
```

## Do and don't

### Do

- Pass only the handlers the conversation supports; each one shows its button.
- Put rare or destructive actions (Copy, Edit, Delete) in a DropdownMenu as children.
- Keep the quick reactions to six or fewer.

### Don't

- Do not put text buttons in the toolbar; it holds icon buttons only.
- Do not show the toolbar on every message at once; MessageBubble shows it on hover, focus or a tap.
- Do not add a second reaction row under the toolbar; reactions show on the message.

## Props

| Name | Type | Values | Default | Description |
| --- | --- | --- | --- | --- |
| `onReact` | `(emoji: string) => void` |  |  | Shows React, and is called with the emoji picked. |
| `quickReactions` | `string[]` |  |  | The reactions offered first. Default 👍 ❤️ 😂 😮 😢 🙏. |
| `frequentEmoji` | `string[]` |  |  | Emoji shown first in the full picker. Default: the quick reactions. |
| `onReply` | `() => void` |  |  | Shows Reply. Put the message in the Composer's replyTo. |
| `onForward` | `() => void` |  |  | Shows Forward. |
| `pinned` | `boolean` |  | `false` | Whether the message is pinned. Pin is pressed while it is. |
| `onPinnedChange` | `(pinned: boolean) => void` |  |  | Shows Pin, and is called with the new pinned state. |
| `onSelect` | `() => void` |  |  | Shows Select. Turn on selection mode in the MessageList with this message picked. |
| `labels` | `{ toolbar?: string; react?: string; reply?: string; forward?: string; pin?: string; select?: string; moreReactions?: string; quickReactions?: string; emojiPicker?: EmojiPickerLabels }` |  |  | Names of the toolbar and its buttons. Defaults: Message actions, React, Reply, Forward, Pin, Select, More reactions, Quick reactions. Vietnamese: Thao tác tin nhắn, Bày tỏ cảm xúc, Trả lời, Chuyển tiếp, Ghim, Chọn, Thêm cảm xúc, Cảm xúc nhanh. |
| `children` | `node` |  |  | More controls after the built-in ones, such as a DropdownMenu with Copy, Edit and Delete. Use ghost icon Buttons in size sm. |

## Anatomy

| Part | Description |
| --- | --- |
| `root` | The toolbar: the raised fill with a ring and shadow-med, 4px of padding. |
| `action` | Each built-in action: a ghost icon Button in size sm with a Tooltip. React, Reply, Forward, Pin and Select, in that order. |
| `popover` | The Popover React opens above the toolbar. |
| `quick` | The row of quick reactions with a More reactions button. |
| `reaction` | One quick reaction button, the size of an md control, at the xl text size. |
| `picker` | The EmojiPicker shown after More reactions. |

## Accessibility

Role: `toolbar`

| Keys | Action |
| --- | --- |
| `Tab` | Moves into the toolbar, to the button that last had focus. The toolbar is one tab stop. |
| `Arrow Left / Arrow Right` | Moves to the previous or next button, wrapping around. Follows right-to-left. |
| `Home / End` | Moves to the first or the last button. |
| `Enter / Space` | Runs the focused action. On React, opens the reactions. |
| `Escape` | Closes the reactions and returns focus to React. |

- A toolbar named by labels.toolbar (EN `Message actions`, VI `Thao tác tin nhắn`).
- Every button is an icon button named by its action and shows the same words in a Tooltip.
- Pin is a toggle button: aria-pressed is true while the message is pinned, and its icon turns filled.
- The quick reactions are buttons named by the emoji's name, such as EN `thumbs up`. More reactions opens the EmojiPicker and focuses its search.
- Only actions with a handler show, so the toolbar never offers something that does nothing.

## Install

```bash
npx werewolf-ui add message-actions
```

Run `npx werewolf-ui init` once in your app before adding components. Init sets up tokens, their CSS import and agent rules. Add installs this component and its dependencies while preserving your theme. See [Installation](https://www.werewolf-ui.dev/docs/installation.md) for requirements and the alternative registry setup.
