94 / 122 · Thread
Shared conversation
A read-only transcript someone sent you, with a way to pick it up yourself.
Draft restore across threadsshared by harry · 2 days ago
Why did the draft survive the thread switch?
The composer read a slot keyed by the old thread. Clearing it on switch fixes it at the source.
read only
Installation
npx shadcn@latest add "@assistant-ui/elements-shared-conversation"
Usage
import { SharedConversation } from "@/components/elements/shared-conversation";
<SharedConversation
title="Draft restore across threads"
sharedBy="harry"
sharedAt="2 days ago"
turns={turns}
onContinue={fork}
/>Props
title*stringName of the shared thread.
sharedBy*stringWho shared it.
sharedAt*stringPre-formatted share time.
turns*SharedTurn[]The transcript, read only.
onContinue() => voidCalled to fork the transcript into the reader's own thread.
classNamestringExtra classes merged onto the root.
Source
shared-conversation.tsx"use client";
import { LinkIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import { inkButton, mono, paper } from "./surfaces";
export interface SharedTurn {
id: string;
role: "user" | "assistant";
text: string;
}
export function SharedConversation({
title,
sharedBy,
sharedAt,
turns,
onContinue,
className,
}: {
title: string;
sharedBy: string;
sharedAt: string;
turns: readonly SharedTurn[];
onContinue?: () => void;
className?: string;
}) {
return (
<div
className={cn(
paper,
"flex w-full max-w-sm flex-col overflow-hidden rounded-2xl",
className,
)}
>
<div className="flex items-center gap-2.5 px-4 pt-3.5 pb-3">
<LinkIcon className="text-foreground/30 size-3.5 shrink-0" />
<div className="flex min-w-0 flex-1 flex-col">
<span className="truncate text-[13.5px] font-medium">{title}</span>
<span className={cn(mono, "text-foreground/30 truncate")}>
shared by {sharedBy} · {sharedAt}
</span>
</div>
</div>
<div className="border-foreground/[0.07] flex flex-col gap-2.5 border-t px-4 py-3.5">
{turns.map((turn) => (
<div
key={turn.id}
className={cn(
"text-[13px] leading-relaxed",
turn.role === "user"
? "bg-foreground/[0.05] ms-auto max-w-[85%] rounded-2xl px-3 py-2"
: "text-foreground/70",
)}
>
{turn.text}
</div>
))}
</div>
<div className="border-foreground/[0.07] flex items-center gap-2 border-t px-4 py-3">
<span className={cn(mono, "text-foreground/30")}>read only</span>
<button
type="button"
onClick={onContinue}
className={cn(
inkButton,
"ms-auto flex h-8 items-center rounded-full px-3.5 text-xs font-medium",
)}
>
Continue in your own chat
</button>
</div>
</div>
);
}