Nasaq

Comment Thread

Threaded comments with one reply level, mention chips, badges for agents and clients, a review badge for pending comments and a sign-in prompt.

PreviewOpen ↗

Code

<CommentThread  comments={comments}  currentUser={me}  suggestions={people}  onSubmit={async ({ body, mentions, parentId }) => save(body, mentions, parentId)}  onEdit={async (id, body) => edit(id, body)}  onDelete={async (id) => remove(id)}/>

Collaboration · beta

Live examples and controls: Comment Thread in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/comment-thread.json

A discussion under an issue, a document or a ticket. Every action awaits your callback, so a failed post keeps the text and shows the error.

When to use

  • Discussion on one record, with replies and @mentions.
  • Comments from people, agents, clients and bots in one list.

When not to use

  • A live chat: use a chat component.
  • A flat activity feed: use Timeline.

Import

import { CommentThread } from "@fadymondy/nasaq/web";

Quick start

<CommentThread
  comments={comments}
  currentUser={me}
  suggestions={people}
  onSubmit={async ({ body, mentions, parentId }) => save(body, mentions, parentId)}
  onEdit={async (id, body) => edit(id, body)}
  onDelete={async (id) => remove(id)}
/>

Anatomy

CommentThread          data-slot="comment-thread"
├─ header              title and count
├─ thread              a root comment and its replies (one level)
│  ├─ author, badge    agent, client or bot, and "Awaiting review"
│  ├─ body             Markdown, mention chips
│  └─ actions          Reply, Edit, Delete, Approve (button menu and context menu)
└─ composer            MentionTextarea, or a sign-in prompt

API

PropTypeDefaultDescription
commentsThreadComment[]requiredFlat list in any order. parentId makes a reply.
currentUserCommentAuthornoneTheir comments can be edited and deleted.
signedInbooleantrueFalse shows a sign-in prompt instead of the composer.
suggestionsMentionOption[][]People offered by @.
onSubmit({ body, mentions, parentId? }) => Promise<...>nonePost or reply. Omit for a read-only thread.
onEdit / onDelete / onApprove(id, ...) => Promise<...>noneOmit to hide the action.
canModeratebooleanfalseApprove pending comments and edit or delete any comment.
onSignIn() => voidnoneThe sign-in button.
renderMention(mention, chip) => ReactNodenoneWrap a chip, for example in a hover card.
hideHeaderbooleanfalseHide the title and count.
labelsCommentThreadLabelsen / arEvery string.

Examples

  • Signed out: signedIn={false} with onSignIn.
  • Moderation: a comment with pending: true shows a badge; a moderator gets Approve.

Accessibility

Each thread is a list; the composer is labelled; errors use role="alert". Row actions open from a button menu or from a context-click, Shift+F10 or the Menu key.

RTL & i18n

English and Arabic built in, labels overrides every string. Mixed-direction bodies use dir="auto"; times use the locale.

Styling & tokens

Semantic tokens only. Reply indent uses logical padding.

Do / Don't

  • Do return { error } from a callback instead of throwing.
  • Do not nest replies deeper: a reply to a reply joins the same thread.

Lab

https://docs.nasaqui.com/?path=/docs/components-collaboration-comment-thread--docs

On this page