Skip to content
Sign in
ConversationThread summaryMenu

Thread summary

A catch-up card for long threads and returning users: summary points, key decisions, open questions and files touched, each with a Jump to link. Collapsed and expanded, with regenerate, a stale note and a streaming state while the summary is written.

Summary, decisions, open questions and files touched, each linking back into the thread.

Installation

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

Usage

tsx
import { ThreadSummary } from "@/components/ui/chatcn/thread-summary"

<ThreadSummary
  meta="86 messages since yesterday"
  summary={[{ text: "Sessions move to Postgres, keyed by a hashed token.", messageId: "m-4" }]}
  decisions={decisions}
  questions={questions}
  files={[{ path: "src/auth/session-store.ts", status: "added" }]}
  onJump={(id) => scrollToMessage(id)}
  onRegenerate={regenerate}
/>

Generate the summary however you like, for example with a structured output call that returns the four lists with message ids. Collapsed, the card shows the first three points and a footer that counts what is hidden; expanding reveals the rest. Pass newMessages when the thread has moved on since the summary, and Update appears next to the count.

Open questions use the amber needs-you tone with a question mark icon. File letters follow the changed files badges: green A, amber M, red D, blue R, each with a hidden word for screen readers. Long paths give up their directory first, so the file name stays readable.

Examples

Writing the summary

status="loading" shows static bars at the size of three points while the thread is read. streaming appends points in place with the caret on the newest one, and keeps the panel at its natural height so nothing animates while text arrives.

Reading, then writing: points append in place with the caret on the newest one.

States

Collapsed with new messages since, reading, failed and nothing to summarize.

Props

PropTypeNotes
summary, decisions, questions{ id?, text, messageId? }[]Points. messageId adds Jump to
files{ path, status?, messageId? }[]status: "added" | "modified" | "deleted" | "renamed"
onJump(messageId: string) => voidScroll the thread to the source
status"loading" | "streaming" | "done" | "error"Defaults to done
titleReactNodeDefaults to "Catch up"
metaReactNodeQuiet detail after the title
loadingTextReactNodeFor example "Reading 86 messages"
errorText, onRetryError copy and Retry
onRegenerate() => voidShows the regenerate button and Update
newMessagesnumberMessages since the summary was written
onDismiss() => voidShows a close button
emptyTextReactNodeWhen there is nothing to summarize
collapsedCountnumberPoints shown while collapsed. Defaults to 3
open, defaultOpen, onOpenChangebooleanControlled or uncontrolled

Keyboard

KeyAction
TabMove through Regenerate, each Jump to link and Show more
Enter, SpaceJump, or expand and collapse

Accessibility

  • The card is a labelled section and each list a labelled section with its heading. Jump to links are named after their point.
  • Jump to links appear on hover and stay focusable and visible on focus; on touch screens they are always shown.
  • Loading and writing are announced as a status. Errors use role="alert" and say what to try.

Motion

  • Expanding and collapsing animate height and opacity over 200 ms, measured by Base UI. Instant under reduced motion and while streaming.
  • Jump to links reveal instantly on hover, because the card is scanned quickly.