Skip to content
ConversationMessage actionsMenu

Message actions

The toolbar under a message: copy, retry, edit, feedback, share and more. Visible on the latest reply and on touch, revealed instantly on hover everywhere else.

Pinned on the latest reply, revealed on hover elsewhere.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/message-actions.json

Usage

tsx
import {
  MessageAction,
  MessageActionCopy,
  MessageActionMenu,
  MessageActions,
} from "@/components/ui/chatcn/message-actions"

<MessageActions>
  <MessageActionCopy value={text} label="Copy response" />
  <MessageFeedback onValueChange={rate} />
  <MessageAction label="Retry response" onClick={retry}>
    <RotateCcwIcon />
  </MessageAction>
  <MessageActionMenu items={[{ label: "Branch in new chat", onSelect: branch }]} />
</MessageActions>

Inside a Message, the toolbar reads the message's latest flag and hides itself while it streams. Wrap your app in TooltipProvider so the second tooltip opens instantly.

Props

PropTypeNotes
MessageActions.visiblebooleanKeep visible. Defaults to the message's latest
MessageAction.labelstringAccessible name and tooltip. Use a specific verb
MessageAction.shortcutReactNodeShortcut hint in the tooltip
MessageActionCopyCopyButtonPropsvalue may be a function, read at click time
MessageActionMenu.items{ label, icon?, onSelect?, disabled? }[]The overflow menu

Keyboard

KeyAction
TabFocusing any action reveals the whole toolbar
Enter, SpaceRun the action, or open the menu
↑, ↓ in the menuMove between items
EscClose the menu

Accessibility

  • The toolbar is a toolbar named Message actions. Every icon button has an aria-label.
  • Hidden actions use opacity, not display, so keyboard focus can reach and reveal them.
  • Actions are 28 px with a 44 px hit area on touch screens.

Motion

  • Revealing the toolbar is instant. It happens hundreds of times a day, so an animation would only add lag.
  • The menu opens from its trigger over 180 ms. Opened from the keyboard, it appears without animation.