Conversation
User Message
A sent prompt with attachments, edit-in-place and resend, copy, and a delivery state.
2 variantsMIT
Preview
Translate the onboarding emails into German and keep product names in English.
Sending
Installation
Copies the component into components/ui and installs its dependencies and theme tokens.
pnpm dlx shadcn@latest add https://tuffui.com/r/user-message.jsonUsage
Pass your own data and wire the callbacks to your agent runtime.
import { UserMessage } from "@/components/ui/user-message";
export function Prompt({ message }: { message: Message }) {
return (
<UserMessage
data={{
id: message.id,
content: message.text,
attachments: message.files,
sentAt: formatTime(message.createdAt),
status: message.status, // "sending" | "sent" | "failed"
edited: message.edited,
}}
onEdit={(text) => chat.editAndResend(message.id, text)}
onRetry={() => chat.resend(message.id)}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| data* | UserMessageData | — | The prompt text, attachments, display time and delivery status. |
| onEdit | (text: string) => void | — | Save & resend from the inline editor (Enter saves, Shift+Enter adds a line, Esc cancels). The edit action is hidden without it. |
| onRetry | () => void | — | Shows a Retry button when the status is failed. |
| onCopy | (text: string) => void | — | Called after the text is copied to the clipboard. |
| className | string | — | Extra classes for the root. |
type UserMessageData = {
id: string;
content: string;
attachments?: { id: string; name: string; kind: "image" | "file"; size?: number; previewUrl?: string }[];
sentAt?: string; // display time, e.g. "14:02"
status?: "sending" | "sent" | "failed";
edited?: boolean;
};