Comment Thread
ilinxa/comment-threadFreeBlock
Recursive comment thread with composer, optimistic add, like, and delete, inline expansion past max depth, and realtime subscription hooks.
Install it
npx shadcn@latest add https://ui.ilinxa.com/r/comment-thread.jsonSource
1"use client";23import {4 memo,5 useCallback,6 useEffect,7 useImperativeHandle,8 useMemo,9 useRef,10 useState,11} from "react";12import { cn } from "@/lib/utils";13import {14 DEFAULT_COMMENT_THREAD_LABELS,15 type Comment,16 type CommentThreadHandle,17 type CommentThreadProps,18 type CommentThreadLabels,19} from "./types";20import { useCommentState } from "./hooks/use-comment-state";21import { CommentNode } from "./parts/comment-node";22import {23 CommentComposer,24 type CommentComposerHandle,25} from "./parts/comment-composer";26import { CommentEmptyState } from "./parts/comment-empty-state";27import { defaultRelativeTime } from "./lib/format-time";2829interface CommentThreadInnerProps extends CommentThreadProps {30 ref?: React.Ref<CommentThreadHandle>;31}3233function genTempId(): string {34 if (typeof crypto !== "undefined" && "randomUUID" in crypto) {35 return `temp-${crypto.randomUUID()}`;36 }37 return `temp-${Date.now()}-${Math.random().toString(36).slice(2)}`;38}3940function CommentThreadInner(props: CommentThreadInnerProps) {41 const {42 comments: initialComments,43 variant = "default",44 currentUser,45 maxDepth = 2,46 indentPx = 24,47 bodyMaxLines: bodyMaxLinesProp,48 composerMinRows = 1,49 composerMaxRows = 6,50 submitOnEnter = true,51 pageSize = 10,52 subscribe,53 onSubscribeDelta,54 onAddComment,55 onLikeComment,56 onDeleteComment,57 onReportComment,58 onLoadMore,59 commentActions,60 renderNode,61 renderViewReplies,62 renderComposer,63 composerEmptyState,64 emptyState,65 labels: labelsProp,66 className,67 composerClassName,68 nodeClassName,69 ref,70 } = props;7172 const bodyMaxLines = bodyMaxLinesProp ?? (variant === "compact" ? 2 : 4);7374 const labels = useMemo<75 Required<Omit<CommentThreadLabels, "formatRelativeTime">>76 >(77 () => ({ ...DEFAULT_COMMENT_THREAD_LABELS, ...labelsProp }),78 [labelsProp],79 );8081 const format = useMemo(82 () => labelsProp?.formatRelativeTime ?? defaultRelativeTime,83 [labelsProp?.formatRelativeTime],84 );8586 const { comments, dispatch } = useCommentState({87 initialComments,88 subscribe,89 onSubscribeDelta,90 });9192 const [replyParentId, setReplyParentId] = useState<string | null>(null);93 const replyTriggerRef = useRef<HTMLElement | null>(null);94 const [currentPage, setCurrentPage] = useState(1);95 const [isLoadingMore, setIsLoadingMore] = useState(false);96 const [hasMore, setHasMore] = useState(initialComments.length === pageSize);97// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from ilinxa
All 184 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Account Switcheraccount-switcher | ilinxa | Blocks | Free | 1 dep · 10 files | |
| Account Switcher (deprecated alias)account-switcher-01 | ilinxa | Blocks | Free | no deps | |
| Account Switcher — fixturesaccount-switcher-fixtures | ilinxa | Blocks | Free | no deps | |
| App Sidebarapp-sidebar | ilinxa | Blocks | Free | 1 dep · 37 files | |
| App Sidebar — fixturesapp-sidebar-fixtures | ilinxa | Blocks | Free | no deps | |
| Rich Text Editor (deprecated alias)article-body-01 | ilinxa | Blocks | Free | no deps | |
| Article Metaarticle-meta | ilinxa | Blocks | Free | 1 dep · 4 files | |
| Article Meta (deprecated alias)article-meta-01 | ilinxa | Blocks | Free | no deps |
