Skip to content
Sign in
CollaborationThread commentsMenu

Thread commentsPro

Comment on any message, people and agents alike, with resolve that folds the thread to one line.

ProA comment thread on one sentence of an agent's message, with teammates and the agent replying.

Installation

$ pnpm dlx shadcn@latest add @chatcn-pro/thread-comments

Usage

tsx
import { ThreadComments, CommentCount } from "@/components/ui/chatcn/pro/thread-comments"

<ThreadComments
  quote="I will refund the second charge of $84.20"
  comments={comments}
  currentUser={me}
  typers={typingInThread}
  onReply={(text) => api.comment(messageId, text)}
  resolved={resolved}
  onResolvedChange={setResolved}
  resolvedBy={resolver}
/>

The quoted part of the message sits on top and the comments run down a hairline rail that joins one author's avatar to the next. The composer posts with Enter (Shift Enter for a new line, never during IME composition) and shows who else is typing in its footer through typing-presence. A reply shows as sending until onReply resolves; a rejected one stays in place, marked, with Retry. Resolve folds the thread into a single line that says who resolved it and how many comments it holds; Reopen brings it back. CommentCount is the marker for a message's margin. Pass comments and append on resolve, or defaultComments to let the thread keep its own list.

Examples

States

ProEmpty, resolved and folded, a failed reply, long, loading, read only and the margin markers.

Props

PropTypeNotes
quoteReactNodeThe part commented on
comments, defaultComments{ id, author, body, time?, edited? }[]Controlled or uncontrolled
currentUserCollabMemberAuthor of new replies
onReply(text) => unknown | Promise<unknown>Reject to mark the reply failed
typersTypingPresenceTyper[]Shown in the composer footer
resolved, defaultResolved, onResolvedChange, resolvedByResolve state
loading, disabled, localeStates
labelsPartial<ThreadCommentsLabels>Every string, for translation

Labels

labels covers the title and count, Resolve and Reopen, the resolved line (resolved(by)), both placeholders, sending, failed and Retry, the edited tag, the agent and you tags and the empty state. CommentCount takes label(count, resolved).

Keyboard

KeyAction
EnterPost the reply
Shift EnterNew line
TabResolve, the comments' Retry, the composer and send

Accessibility

  • The thread is a section named by its title; the folded state is a button with aria-expanded.
  • A failed reply is an alert with a Retry button next to it.
  • CommentCount is a button with aria-expanded and a name that includes the count and whether it is resolved.

Motion

New comments rise 4 px and fade in over 200 ms. Reduced motion keeps the fade. Folding and reopening swap without animation so the page does not jump twice.