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.
On this page
Installation
Usage
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.
States
Props
| Prop | Type | Notes |
|---|---|---|
summary, decisions, questions | { id?, text, messageId? }[] | Points. messageId adds Jump to |
files | { path, status?, messageId? }[] | status: "added" | "modified" | "deleted" | "renamed" |
onJump | (messageId: string) => void | Scroll the thread to the source |
status | "loading" | "streaming" | "done" | "error" | Defaults to done |
title | ReactNode | Defaults to "Catch up" |
meta | ReactNode | Quiet detail after the title |
loadingText | ReactNode | For example "Reading 86 messages" |
errorText, onRetry | Error copy and Retry | |
onRegenerate | () => void | Shows the regenerate button and Update |
newMessages | number | Messages since the summary was written |
onDismiss | () => void | Shows a close button |
emptyText | ReactNode | When there is nothing to summarize |
collapsedCount | number | Points shown while collapsed. Defaults to 3 |
open, defaultOpen, onOpenChange | boolean | Controlled or uncontrolled |
Keyboard
| Key | Action |
|---|---|
Tab | Move through Regenerate, each Jump to link and Show more |
Enter, Space | Jump, 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.