Skip to content

feat(chat): add copy-to-clipboard button to message bubbles - #233

Closed
JnyRoad wants to merge 2 commits into
OpenBMB:mainfrom
JnyRoad:feat/chat-message-copy-button
Closed

JnyRoad wants to merge 2 commits into
OpenBMB:mainfrom
JnyRoad:feat/chat-message-copy-button

Conversation

@JnyRoad

@JnyRoad JnyRoad commented Aug 29, 2026

Copy link
Copy Markdown

Summary

Chat messages had no way to copy their text, unlike the copy-to-clipboard affordance under each message in Claude/ChatGPT-style chat UIs. This adds that button to both user and assistant messages in the chat page.

Changes

  • Add a copy button to MessageBubble: merged into the existing feedback row (next to thumbs up/down) for assistant replies, and a standalone row for user messages. Reuses the existing copyTextToClipboard helper and notify toast for success/failure feedback.
  • Hide the button while an assistant reply is still streaming, since the displayed text can change before an in-flight clipboard write resolves (would otherwise show a stale "copied" confirmation against newer text).
  • Guard state updates after the async clipboard write with a mounted ref, so a write that resolves after the component unmounts (e.g. switching sessions mid-copy) doesn't touch state or leave a dangling timer. The ref is reset on effect setup, not just cleared on cleanup, so it survives React StrictMode's dev-mode double mount/unmount cycle.
  • Reset the "copied" confirmation timer via a ref on every click, so a repeated click before the first 1.5s window expires gets its own full confirmation window instead of being cut short by the earlier timer.

Testing

  • cd frontend-enterprise && npx tsc -b — clean
  • cd frontend-enterprise && npx vitest run src/pages/chat — 64 passed

Risks

No obvious risks. Change is scoped to a single component (MessageBubble.tsx) and its test file; no API, schema, or config changes.

Add a copy button to chat messages, matching the copy-to-clipboard
affordance in Claude/ChatGPT-style chat UIs. Assistant replies get the
button merged into the existing feedback row (next to the thumbs
up/down); user messages get a standalone row.

What:
- Reuse the existing copyTextToClipboard helper (lib/clipboard.ts) and
  notify toast for success/failure feedback.
- Hide the button while an assistant reply is still streaming, since
  the displayed text can change before an in-flight clipboard write
  resolves.
- Guard the post-await state updates with a mounted ref so a clipboard
  write that resolves after the component unmounts (e.g. switching
  sessions mid-copy) does not touch state or leave a dangling timer;
  the ref is reset on effect setup (not just cleared on cleanup) so it
  survives React StrictMode's dev-mode double mount/unmount cycle.
- Reset the "copied" confirmation timer via a ref on every click so a
  repeated click before the first window expires gets its own full
  1.5s confirmation instead of being cut short by the earlier timer.

Testing:
- frontend-enterprise: npx tsc -b (clean)
- frontend-enterprise: npx vitest run src/pages/chat (64 passed)
@JnyRoad JnyRoad closed this by deleting the head repository Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant