All blocksFree · Collaboration
Comment Thread
Inline comment thread with avatars and a composer. Local state, drop-in.
This Pro block's preview & source unlock with the library.
Unlock — ₹2,499Install
terminal
npx shadcn@latest add https://blocks.aiskillhub.info/api/registry/comment-threadSource
components/docblocks/comment-thread.tsx
"use client";
import { useState } from "react";
type Comment = { id: string; author: string; initials: string; body: string; time: string };
export function CommentThread({ initial = [] }: { initial?: Comment[] }) {
const [comments, setComments] = useState<Comment[]>(initial);
const [draft, setDraft] = useState("");
return (
<div className="w-80 space-y-3 rounded-xl border border-border bg-surface p-4">
{comments.map((c) => (
<div key={c.id} className="flex gap-3">
<span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary text-[11px] font-semibold text-primary-fg">{c.initials}</span>
<div className="space-y-0.5">
<p className="text-xs"><span className="font-medium">{c.author}</span> <span className="text-muted">{c.time}</span></p>
<p className="text-sm">{c.body}</p>
</div>
</div>
))}
<form
onSubmit={(e) => { e.preventDefault(); if (!draft.trim()) return;
setComments((p) => [...p, { id: crypto.randomUUID(), author: "You", initials: "Y", body: draft, time: "now" }]); setDraft(""); }}
className="flex gap-2"
>
<input value={draft} onChange={(e) => setDraft(e.target.value)} placeholder="Add a comment…"
className="flex-1 rounded-lg border border-border bg-background px-3 py-1.5 text-sm outline-none focus:ring-2 focus:ring-ring" />
<button className="rounded-lg bg-primary px-3 text-sm font-medium text-primary-fg">Send</button>
</form>
</div>
);
}