FORMA Docs

Comment thread

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

import { CommentThread, type ThreadComment } from "@/forma/arc/comment-thread/comment-thread";
Base

In FORMA

  • Liegt in kit/arc/comment-thread und ist über @/forma/arc/comment-thread/comment-thread erreichbar.
  • Farbe, Ecken, Höhen, Abstände, Tiefe, Schrift und Tempo kommen aus der Richtung (core/arc-bridge.ts); Arc behält Verhalten, Tastatur und Federn.

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.

Usage

import { CommentThread, type ThreadComment } from "@/forma/arc/comment-thread/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

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.
currentUser (required)CommentAuthor–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
id (required)string–Stable id.
author (required){ id: string; name: string; avatar?: string }–Author. Initials show without an avatar.
body (required)string–Plain text. "@Full Name" mentions of known people are highlighted.
createdAt (required)string–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.

Keyboard interactions

KeysAction
⌘ + Enter / Ctrl + EnterSends the composer.
@Opens mention suggestions in the composer.
ArrowUp / ArrowDownMove through mention suggestions.
Enter / TabInsert the active mention.
EscapeCloses 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.

Also in activity

  • Timeline: Follow what happened, newest first, grouped by day.

Guidance for AI tools

Comment thread: Threaded comments with replies, reactions, mentions, inline edit, and resolve. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://uiarc.dev/llms.txt

Komponente und Text: Arc UI (MIT, uiarc.dev), angepasst für FORMA.