Comment Thread
motiq/comment-threadFreeComponent
A production comment thread your app persists: root comments + nested replies, mentions, reactions, edit, resolve/reopen, delete, and optimistic send (pending → sent, failed → retry, temp-id replacement, focus preserved). Unread divider and sort. The app owns persistence + permissions.
Live preview
live · rendered by the registry
Rendered by motiq on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.motiq.dev/r/comment-thread.jsonSource
1"use client";23import * as React from "react";4import { motion, AnimatePresence, type Transition } from "motion/react";56import { cn } from "@/lib/utils";7import {8 useReducedMotion,9 useDisclosure,10 useAnchoredPortal,11 useCopy,12 formatTimestamp as defaultFormatTimestamp,13 statusVars,14 streamItemVariants,15 type StatusTone,16} from "@/lib/motiq";1718/* --------------------------------------------------------------------------19 * CommentThread — a review/collaboration discussion that is more than stacked20 * bubbles. It renders threaded replies, mentions, reactions, resolve/reopen,21 * an unread divider, and — its differentiator — an internal OPTIMISTIC send22 * layer: a new or edited comment appears immediately in a "pending" state, then23 * flips to sent, or to "failed" with a Retry action, replacing its temporary id24 * when the app confirms. Focus is preserved across those transitions.25 *26 * Presentation + optimistic UX only: the application owns persistence and27 * permissions. The component renders the `comments` it is given, overlays its28 * own in-flight sends, and calls back so the app can do the real work. When a29 * callback returns a Promise, its resolution/rejection drives pending → sent /30 * failed; the app updates `comments` in that same handler and the overlay is31 * reconciled away by id. Clean-room original.32 * ----------------------------------------------------------------------- */3334export interface CommentAuthor {35 /** Stable identity — drives keys, mention matching, and avatar hue. */36 id: string;37 /** Human name; also the avatar's accessible text. */38 name: string;39 /** Optional avatar image; when absent an initials + hue avatar is generated. */40 avatarUrl?: string;41 /** Optional explicit avatar color (any CSS color). */42 color?: string;43 /** Optional role/handle shown next to the name. */44 role?: string;45}4647export interface Reaction {48 /** The emoji glyph, e.g. "👍". */49 emoji: string;50 /** How many people reacted with it. */51 count: number;52 /** Whether the current user is among them (drives the toggle + label). */53 reactedByMe?: boolean;54 /** Accessible name for the emoji, e.g. "thumbs up". Falls back to the glyph. */55 label?: string;56}5758export interface CommentAttachment {59 id: string;60 name: string;61 /** Small secondary text, e.g. a file size. */62 meta?: string;63 href?: string;64}6566export type CommentStatus = "normal" | "pending" | "failed" | "edited" | "resolved" | "deleted";6768// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from motiq
All 100 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Activity Streamactivity-stream | motiq | Components | Free | 1 dep | |
| Adaptive Safe-Zone Gridadaptive-safe-zone-grid | motiq | Components | Free | no deps | |
| Agent Run Timelineagent-run-timeline | motiq | Components | Free | 1 dep | |
| AI Response Streamai-response-stream | motiq | Components | Free | 1 dep | |
| Animated Accordionanimated-accordion | motiq | Components | Free | 2 deps | |
| Animated Buttonanimated-button | motiq | Components | Free | 1 dep | |
| Animated Dialoganimated-dialog | motiq | Components | Free | 2 deps | |
| Animated Gridanimated-grid | motiq | Components | Free | 2 deps |
