‹ components

CommentThread

draftv0.9.0·open in canvas

Comment bottom-sheet: threaded rows + a pinned composer. Built on `Sheet`.

Installnpx shadcn add @cids/comment-thread
Live demo

Motion · tap to replay

honors reduced-motion

Sheet slide + drag-dismiss; ♥ and send buttons press-scale `0.96`.

Brand chip remounts on tap · highlighted tokens are named in this component's doc · spring is budgeted to human feedback only.

import { CommentThread, type Comment } from "@/design-system";

<CommentThread
  open={open}
  onOpenChange={setOpen}
  comments={comments}
  onLike={(i, replyIndex) => like(i, replyIndex)}
  onSubmit={(text) => post(text)}
/>

Tokens · live

Resolves in the active theme — flip the toggle above to verify.

States · from doc

Parsed from the doc. Interact with the live demo for hover/active.

**Empty vs N** — title pluralizes.**Reply** — indented 36px with a left bordersingle level.**Liked** — ♥ + count in `text-brand`.turns `sell` if negative .

Comment bottom-sheet: threaded rows + a pinned composer. Built on Sheet.

Anatomy

┌ Sheet · "12 comments" ─────────────┐
│ ◐28 @handle time                   │
│     body 14/1.5                    │
│     ♥ 5   reply                    │
│   ↳ ◐28 @handle (reply, indent 36) │ ← one level, border-l
│ …                                  │
├────────────────────────────────────┤
│ [ textarea            ] ( ↑ )      │ ← footer; counter ≤40 left
└──────────────────────────────────────┘

Props

PropTypeDefaultNotes
open / onOpenChangeboolean / (b) => void—Controlled, forwarded to Sheet.
commentsComment[]—{ author, time, body, likes, liked?, replies? }. Replies are one level.
onLike(index, replyIndex?) => void—replyIndex set when a reply's ♥ is tapped.
onSubmit(text: string) => void—Composer send (trimmed, non-empty).

Motion

Sheet slide + drag-dismiss; ♥ and send buttons press-scale 0.96.

A11y

Self-contained: copy the folder into any Tailwind+React app, or use the install command above. Docs and this page render the same file on disk — they cannot drift.