Comment thread

Threaded comments with replies, reactions, mentions, inline edit, and resolve.

npm install https://animui.stracture.net/__local/package.tgz
Live · keyboard ready

Hero headline

4 comments
  • Jasmine Brooks2h

    Can we try a shorter headline here? @Emma Collins had a version that fit on one line at 390 px.

    • Emma Collins1h

      Yes, “Plan less. Ship more.” Dropping it into the file now.

    • Marcus Johnson48m

      Works for me. It also saves the second line on mobile.

  • Daniel Kim30m

    Once this lands I'll update the social image copy to match. @Chloe Nguyen can you check the click through numbers after?

Signed in as Emma Collins

  • 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.
  • 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.

Installation

Install animui once, then import any component or block from its typed package entry.

animui · 250 components and blocks

React 19 and React DOM 19 are required. The package includes Free and Pro entries, styles and TypeScript declarations.

npm install https://animui.stracture.net/__local/package.tgz

Load the stylesheet once at your app root, then use the typed component import:

import 'animui/styles.css';
import { CommentThread } from 'animui/comment-thread';

Read the Code tab for the implementation files and the API reference below for required props.

Download animui 0.3.0 · Agent guide
example.tsx
import { CommentThread, type ThreadComment } from "animui/comment-thread"; export function HeadlineDiscussion({ initial, me }: { initial: ThreadComment[]; me: { id: string; name: string; avatar?: string } }) {  return (    <CommentThread      title="Hero headline"      currentUser={me}      defaultComments={initial}      onCommentsChange={(_, event) => syncComment(event)}      onResolvedChange={resolved => setThreadResolved("hero", resolved)}    />  );}

API reference

2 parts. The first is the root.

CommentThread

A threaded discussion: nested replies that collapse, reactions with rolling counts, in-place edit and delete, @mention autocomplete, and resolving that folds the thread into a chip.

PropTypeDefaultDescription
commentsThreadComment[]–The comment tree (controlled).
defaultCommentsThreadComment[][]Initial tree when uncontrolled.
onCommentsChange(comments: ThreadComment[], event: CommentThreadEvent) => void–Called with the full next tree and what changed: reply, edit, delete, or react.
currentUserRequiredCommentAuthor–The person writing. Their comments can be edited and deleted.
peopleCommentAuthor[]–People who can be mentioned. Defaults to everyone in the thread.
resolvedboolean–Resolved state (controlled).
defaultResolvedbooleanfalseInitial resolved state.
onResolvedChange(resolved: boolean) => void–Called on Resolve and Reopen.
titleReactNode–What the thread is about, shown in the header, such as "Hero headline".
reactionsstring[]["👍", "❤️", "🎉", "👀", "🚀", "✅"]Emoji offered by the reaction picker.
placeholderstring–Composer placeholder.
maxDepthnumber2Replies deeper than this attach to the deepest allowed parent.
nowLabelstring–createdAt label for comments written now.
labelsCommentThreadLabels–Words for localization, every visible word and accessible name: reply, edit, delete, cancel, send, save, resolve, resolved, reopen, empty, edited, deleteConfirm, deletedText, deletedComment, editComment, hideReplies, cancelReply, addReaction, closeReactions, reactions, mentions and thread. Words with a count or a name are functions: commentCount, peopleCount, showReplies, replyingTo, reactWith and reactionCount. Any key left out keeps its English default.
classNamestring–Extra class on the section.
refRef<HTMLElement>–The section element.

ThreadComment

One comment in the tree.

PropTypeDefaultDescription
idRequiredstring–Stable id.
authorRequired{ id: string; name: string; avatar?: string }–Author. Initials show without an avatar.
bodyRequiredstring–Plain text. "@Full Name" mentions of known people are highlighted.
createdAtRequiredstring–Display label such as "2h" or "Sep 18".
editedboolean–Shows an edited mark.
deletedboolean–A deleted comment with replies stays as a quiet placeholder.
reactions{ emoji: string; users: string[] }[]–Reactions and who gave them.
repliesThreadComment[]–Nested replies.
⌘+EnterorCtrl+Enter
Sends the composer.
@
Opens mention suggestions in the composer.
ArrowUporArrowDown
Move through mention suggestions.
EnterorTab
Insert the active mention.
Escape
Closes suggestions, then cancels an edit or reply; also closes the reaction picker or delete confirmation.
  • 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.
  • 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.
  • 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.
  • 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

Give your coding assistant the Markdown reference instead of screenshots.

  • 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.

The full library index for assistants is at /llms.txt.