Comment thread
Threaded comments with replies, reactions, mentions, inline edit, and resolve.
datanew
Preview
Comment thread preview
Live · keyboard ready
Hero headline
3 commentsElia Kuratli2h The preview pane is 64px short of the section on small screens.
Ada Lovelace1h Fixed. We also dropped the shadow so the divider reads clearer.
You48m Great — the portal to body sorts the containing block too.
This comment was deleted
When to use
- Review threads on documents, designs, tickets, or pull requests.
- Discussions that need replies, reactions, mentions, and a resolved state.
- Sidebars of feedback attached to one object.
When not to use
- Use chat-thread for real-time back-and-forth conversation.
- Use ai-chat for assistant conversations with streaming replies.
- Use mention-input alone when you only need a composer.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "comment-thread",
"type": "registry:ui",
"title": "Comment thread",
"description": "Threaded comments with replies, reactions, mentions, inline edit, and resolve.",
"categories": [
"data"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/comment-thread/comment-thread.tsx",
"type": "registry:component",
"target": "@components/manicat/comment-thread/comment-thread.tsx"
},
{
"path": "registry/components/comment-thread/comment-thread.module.css",
"type": "registry:component",
"target": "@components/manicat/comment-thread/comment-thread.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/comment-thread",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/comment-thread",
"markdown": "https://uiarc.dev/components/comment-thread/markdown",
"tags": [
"data",
"new"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { CommentThread } from "@/components/manicat/comment-thread/comment-thread";
import type { CommentAuthor, ThreadComment } from "@/components/manicat/comment-thread/comment-thread";
const commentPeople: CommentAuthor[] = [
{ id: "eli", name: "Elia Kuratli" },
{ id: "ada", name: "Ada Lovelace" },
{ id: "me", name: "You" },
];
const threadComments: ThreadComment[] = [
{
id: "c1",
author: commentPeople[0],
body: "The preview pane is 64px short of the section on small screens.",
createdAt: "2h",
reactions: [{ emoji: "👍", users: ["ada"] }],
},
{
id: "c2",
author: commentPeople[1],
body: "Fixed. We also dropped the shadow so the divider reads clearer.",
createdAt: "1h",
replies: [
{ id: "c3", author: commentPeople[2], body: "Great — the portal to body sorts the containing block too.", createdAt: "48m" },
{ id: "c4", author: commentPeople[0], body: "Thanks for catching that.", createdAt: "26m", deleted: true },
],
},
];
export function CommentThreadExample() {
return (
<CommentThread
defaultComments={threadComments}
currentUser={commentPeople[2]}
people={commentPeople}
title="Hero headline"
reactions={["👍", "❤️"]}
/>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Review comments Threaded comments with replies, reactions and mentions on a design review.
Review comments
Threaded comments with replies, reactions and mentions on a design review. preview
Live · keyboard ready
Hero headline
3 commentsElia Kuratli2h The preview pane is 64px short of the section on small screens.
Ada Lovelace1h Fixed. We also dropped the shadow so the divider reads clearer.
You48m Looks good on mobile too.
review-comments-threaded-comments-with-replies-reactions-and-mentions-on-a-design-review-.tsxtsx
"use client";
import { CommentThread } from "@/components/manicat/comment-thread/comment-thread";
import type { CommentAuthor, ThreadComment } from "@/components/manicat/comment-thread/comment-thread";
const people: CommentAuthor[] = [
{ id: "eli", name: "Elia Kuratli" },
{ id: "ada", name: "Ada Lovelace" },
{ id: "me", name: "You" },
];
const comments: ThreadComment[] = [
{
id: "c1",
author: people[0],
body: "The preview pane is 64px short of the section on small screens.",
createdAt: "2h",
reactions: [{ emoji: "👍", users: ["ada"] }],
},
{
id: "c2",
author: people[1],
body: "Fixed. We also dropped the shadow so the divider reads clearer.",
createdAt: "1h",
replies: [{ id: "c3", author: people[2], body: "Looks good on mobile too.", createdAt: "48m" }],
},
];
export function CommentThreadReviewExample() {
return (
<div className="w-full max-w-md">
<CommentThread defaultComments={comments} currentUser={people[2]} people={people} title="Hero headline" reactions={["👍", "❤️"]} />
</div>
);
}
Keyboard interactions
| Keys | Action |
|---|---|
| ⌘ + Enter / Ctrl + Enter | Sends the composer. |
| @ | Opens mention suggestions in the composer. |
| ArrowUp / ArrowDown | Move through mention suggestions. |
| Enter / Tab | Insert the active mention. |
| Escape | Closes suggestions, then cancels an edit or reply; also closes the reaction picker or delete confirmation. |
Accessibility
- The composer is a combobox with a listbox of people and aria-activedescendant.
- Each comment is an article labelled with author and time; deleted ones read "Deleted comment".
- Reaction chips are toggle buttons with aria-pressed and a label like "👍 3, including you".
- Reply toggles expose aria-expanded; icon-only actions have specific labels.
Motion
- The thread height springs when replies expand, comments arrive, or the thread folds into the resolved chip.
- Reaction counts roll to the new value; chips move with layout animation as they are added or removed.
- Edit, confirm, and picker rows slide in from the side.
- Reduced motion swaps content without travel and turns off transitions.
Responsive behavior
- Below 420px the composer hides its avatar and nested replies indent less (12px).
- Hover styles only apply on fine pointers; every action is a visible button on touch.
Performance
- Each change rebuilds the tree immutably and renders every comment; paginate or collapse very long threads.
- Reply nesting is capped by maxDepth, which keeps indentation and render depth bounded.
Notes for AI
- Choose it for comments attached to a document, design, or record. Persist changes with the event passed to onCommentsChange rather than diffing trees.
- currentUser decides which comments show Edit and Delete; enforce the same rule on your server.
- Deleting a comment with replies keeps a placeholder so the thread structure survives.