AI output is raw material, not a finished artifact — users need to paste it into email, docs, code editors, or CRMs. When response messages are frozen static text with no copy button and user messages cannot be edited to refine the prompt, every downstream use forces manual text selection and retyping. That friction compounds on mobile, where text selection is fiddly, and it pushes power users to ChatGPT or Claude where the controls exist.
High because it blocks the primary value loop — putting AI output to use outside the chat surface.
At minimum add a copy-to-clipboard button to every assistant message using navigator.clipboard.writeText(message.content) with a 2-second confirmation state. For user messages, store a mutable content field and render an edit affordance that truncates messages after the edited turn before triggering reload(). Land both in src/components/chat/message-bubble.tsx.
<button onClick={() => navigator.clipboard.writeText(message.content)} aria-label="Copy response">Copy</button>
ID: ai-ux-patterns.core-interaction.response-editing
Severity: high
What to look for: Count all message component types (user messages and AI response messages). For each type, enumerate the available content modification actions: inline editing (textarea/contenteditable), copy-to-clipboard, edit-and-regenerate, or dedicated edit mode. Check for edit icons, pencil icons, or right-click/long-press menu handlers on message elements. Report the ratio of message types with at least 1 modification action.
Pass criteria: Users can either (a) edit the AI response text in-place, (b) edit their own prior message to trigger a new response, or (c) both. A copy-to-clipboard button on responses is a valid minimum for content editing. At least 1 content modification mechanism must be implemented. Report: "X of Y message types support content modification."
Fail criteria: AI response messages and user messages are entirely static — no editing, no copy button, no mechanism to modify or reuse the content.
Skip (N/A) when: Same as regeneration-button.
Detail on fail: "No copy, edit, or content-modification control found on AI response messages or user messages".
Remediation: At minimum, add a copy button to AI responses. Most users want to use AI output somewhere else.
const [copied, setCopied] = useState(false)
const handleCopy = async () => {
await navigator.clipboard.writeText(message.content)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
<button onClick={handleCopy} aria-label="Copy response">
{copied ? <CheckIcon className="w-4 h-4" /> : <CopyIcon className="w-4 h-4" />}
{copied ? 'Copied' : 'Copy'}
</button>
For user message editing, store messages in mutable state and render an edit interface:
const handleEditUserMessage = (messageId: string, newContent: string) => {
// Truncate messages after the edited message and regenerate
const editIndex = messages.findIndex(m => m.id === messageId)
setMessages(prev => [...prev.slice(0, editIndex), { ...prev[editIndex], content: newContent }])
reload() // or re-trigger generation
}
Cross-reference: For a comprehensive review of AI chat UI patterns including message editing, see the AI Chat Visibility Audit in the AI-Powered App Pack.