npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dot-react-comment-lib

v1.0.0

Published

High-performance, ultra-customizable nested threaded comments component library for React and Next.js built with MUI, React Hook Form, and Emoji Picker

Downloads

109

Readme

dot-react-comment-lib

High-performance, ultra-customizable nested threaded comments library for React and Next.js, built with Material UI (MUI), emoji-picker-react, react-hook-form, @hookform/resolvers, and @emotion/styled.

npm version License: MIT TypeScript React Next.js Bundle Size


⚡ Key Optimizations

  • 🚀 Blazing Fast & Ultra Lightweight: Only ~31 KB minified bundle size.
  • 💤 Lazy-Loaded Emoji Picker: emoji-picker-react (~300 KB) is loaded dynamically only when the user opens the emoji popover, ensuring instant initial page loads.
  • 🛡️ Zero Unnecessary Re-Renders: Every subcomponent is optimized with React.memo and stable callback selectors. Reacting or editing one comment will never re-render the whole thread tree.
  • 🔄 Universal Database Schema Adapter: Works directly with ANY database entity (RoomChatEntity, Prisma, Supabase, MongoDB, REST APIs) — automatically converts flat database rows into nested threads on the fly.
  • 🎭 Complete Business Rules Freedom: Easily toggle user avatars on/off, switch between nested vs flat linear comments, limit nesting depth, and customize CSS on every element.

📊 With vs. Without Customization Overview

| Feature | WITHOUT Customization (Default) | WITH Customization | | :------------------------------ | :------------------------------------------------------- | :------------------------------------------------------------------- | | Data Schema | Standard{ id, parentId, content, createdAt, author } | Any DB Schema (uuid, message_parent_uuid, message, etc.) | | Comment Threading | Multi-level nested tree (enableNesting: true) | Simple flat linear comments (enableNesting: false) | | Nesting Depth | Unlimited (maxDepth: Infinity) | Limited to 1, 2, 3, or N levels | | User Images / Avatars | Displayed with circle shape & initials fallback | Hidden completely (showAvatars: false) or custom shapes | | CSS & Styles | Modern clean MUI theme | Custom CSS /styles / classes for every component | | Permissions | Authors can edit/delete own comments | Custom role functions (Admin, Moderator, Guest read-only) | | Reactions & Emojis | Quick reactions + full lazy-loaded emoji picker | Toggleable on/off, custom quick emoji list | | Soft Deletions | "[This comment has been deleted]" placeholder | Hard remove (softDeleteHandling: 'hide') |


📦 Installation

npm install dot-react-comment-lib

Peer Dependencies

npm install @mui/material @mui/icons-material @emotion/react @emotion/styled react-hook-form @hookform/resolvers zod emoji-picker-react

🚀 Usage Guide

1. Usage WITHOUT Customization (Zero Configuration)

If you have standard comment objects, just pass comments and currentUser. It works instantly out-of-the-box:

'use client';

import { NestedComments } from 'dot-react-comment-lib';

const simpleComments = [
  {
    id: '1',
    parentId: null,
    content: 'This is a top-level comment!',
    createdAt: '2025-02-14T08:00:00.000Z',
    author: { id: 'u1', name: 'Aarav Sharma' },
  },
  {
    id: '2',
    parentId: '1',
    content: 'This is an automatic reply to comment #1.',
    createdAt: '2025-02-14T08:30:00.000Z',
    author: { id: 'u2', name: 'Priya Patel' },
  },
];

export default function BasicComments() {
  return (
    <NestedComments
      comments={simpleComments}
      currentUser={{ id: 'u1', name: 'Aarav Sharma' }}
      onSubmitComment={({ content, parentId }) => {
        console.log('Submitting:', content, 'Reply to:', parentId);
      }}
    />
  );
}

2. Usage WITH Database Schema Mapping

A. TypeORM RoomChatEntity Schema (schema="room-chat")

If your backend database matches the RoomChatEntity structure (uuid, message_parent_uuid, message, created_at, deleted_at), pass schema="room-chat":

import { NestedComments } from 'dot-react-comment-lib';

export function RoomChatComponent({ dbRows }) {
  return (
    <NestedComments
      comments={dbRows} // Flat rows from RoomChatEntity
      schema="room-chat"
      currentUser={{ id: 'usr-1', name: 'Aarav Sharma', role: 'Admin' }}
      onSubmitComment={async ({ content, parentId }) => {
        // Save to TypeORM / database endpoint
      }}
    />
  );
}

B. Custom Database Schema Adapter (Prisma, MongoDB, REST)

Map any database structure in just a few lines:

import { NestedComments, CommentFieldMapping } from 'dot-react-comment-lib';

interface PostCommentEntity {
  comment_id: string;
  reply_to_id?: string | null;
  body_text: string;
  timestamp: string;
  user_info: {
    user_id: string;
    display_name: string;
    avatar_link?: string;
  };
}

const customAdapter: CommentFieldMapping<PostCommentEntity> = {
  idKey: 'comment_id',
  parentIdKey: 'reply_to_id',
  contentKey: 'body_text',
  createdAtKey: 'timestamp',
  authorKey: (item) => ({
    id: item.user_info.user_id,
    name: item.user_info.display_name,
    avatarUrl: item.user_info.avatar_link,
  }),
};

export function CustomDatabaseComments({ data }) {
  return (
    <NestedComments
      comments={data}
      schema={customAdapter}
      currentUser={{ id: 'u1', name: 'Alex' }}
    />
  );
}

3. Usage WITH Business Rules

A. Hide User Images Completely (showAvatars: false)

When corporate privacy rules dictate that no user photos should be shown:

<NestedComments
  comments={comments}
  config={{
    showAvatars: false, // User photos and avatars are completely hidden
  }}
/>

B. Simple One-by-One Linear Comments (enableNesting: false)

When you want a sequential flat timeline without replies or indentation:

<NestedComments
  comments={comments}
  config={{
    enableNesting: false, // Renders flat sequential comments without nesting
  }}
/>

C. Limit Nesting Depth (maxDepth)

Restrict replies to a specific indentation level (e.g. max 2 levels):

<NestedComments
  comments={comments}
  config={{
    maxDepth: 2, // Only allows 2 levels of reply depth
  }}
/>

D. Avatar Shapes & Custom Styling

<NestedComments
  comments={comments}
  config={{
    avatarShape: 'rounded', // 'circle' | 'rounded' | 'square'
    showThreadLines: true,  // Draw vertical connector lines
    collapsible: true,      // Allow collapsing branches
    enableEmojiPicker: true,// Lazy-loaded emoji picker popover
  }}
/>

4. Usage WITH Custom CSS & Granular Styling (styles & classes)

You can customize the styling, colors, borders, and shadows of every single element in the UI:

<NestedComments
  comments={comments}
  styles={{
    // Root container
    root: {
      p: 2,
      borderRadius: 4,
      background: 'rgba(255, 255, 255, 0.8)',
      boxShadow: '0 8px 32px rgba(0,0,0,0.06)',
    },
    // Header & counters
    header: { pb: 2, borderBottom: '2px solid #e2e8f0' },
    title: { color: '#1e293b', fontWeight: 800 },
    countBadge: { bgcolor: '#6366f1', color: '#ffffff' },
  
    // Main composer & reply box
    composer: { my: 2 },
    composerInput: {
      borderRadius: 3,
      border: '2px solid #6366f1',
    },
    composerSubmitButton: {
      bgcolor: '#6366f1',
      '&:hover': { bgcolor: '#4f46e5' },
    },
  
    // Comment row cards
    commentItem: {
      p: 1.5,
      borderRadius: 2.5,
      '&:hover': { bgcolor: 'action.hover' },
    },
    authorName: { color: '#4f46e5', fontWeight: 700 },
    commentBody: { fontSize: '0.95rem', lineHeight: 1.6 },
  
    // Emoji reaction chips
    reactionChip: {
      borderRadius: '8px',
      border: '1.5px solid #e2e8f0',
    },
    activeReactionChip: {
      bgcolor: 'rgba(99, 102, 241, 0.15)',
      borderColor: '#6366f1',
    },
  
    // Thread lines
    threadLine: { bgcolor: '#6366f1', width: '2px' },
  }}
  classes={{
    root: 'my-custom-wrapper',
    composer: 'my-custom-composer',
    commentItem: 'my-custom-card',
  }}
/>

5. Usage WITH Granular Role Permissions

<NestedComments
  comments={comments}
  currentUser={currentUser}
  permissions={{
    // Disable replies for guests
    canReply: (comment, user) => user?.role !== 'Guest',
    // Only Admins or comment authors can edit
    canEdit: (comment, user) => user?.role === 'Admin' || comment.author.id === user?.id,
    // Only Admins or comment authors can delete
    canDelete: (comment, user) => user?.role === 'Admin' || comment.author.id === user?.id,
    // Only Admins and Authors can pin comments
    canPin: (comment, user) => user?.role === 'Admin' || user?.role === 'Author',
  }}
/>

6. Headless State Management: useCommentTree Hook

For optimistic UI updates with custom API calls:

import { useCommentTree, NestedComments } from 'dot-react-comment-lib';

export function OptimisticComments({ initialData }) {
  const {
    comments,
    addComment,
    editComment,
    deleteComment,
    reactToComment,
    totalComments,
  } = useCommentTree({
    initialData,
    schema: 'room-chat',
  });

  return (
    <NestedComments
      comments={comments}
      onSubmitComment={async ({ content, parentId }) => {
        addComment(content, parentId); // Optimistic UI update
        await api.saveComment({ content, parentId });
      }}
      onEditComment={async ({ id, content }) => {
        editComment(id, content);
        await api.updateComment(id, content);
      }}
      onDeleteComment={async ({ id }) => {
        deleteComment(id, true);
        await api.deleteComment(id);
      }}
      onReactComment={async ({ id, emoji }) => {
        reactToComment(id, emoji);
        await api.toggleReaction(id, emoji);
      }}
    />
  );
}

📖 Component Props Reference

<NestedComments />

| Prop | Type | Default | Description | | :------------------ | :--------------------------------------------------- | :--------------------- | :------------------------------------------------------------------------------ | | comments | T[] | [] | Array of raw comment data (flat list or nested tree). | | schema | CommentFieldMapping<T> \| 'room-chat' \| 'default' | 'default' | Database schema field adapter configuration. | | currentUser | CommentAuthor | undefined | The currently logged-in user object. | | config | NestedCommentsConfig | {} | Business rules and UI configurations (see table below). | | permissions | CommentPermissions<T> | {} | Permission predicates for reply, edit, delete, pin, react, report. | | styles | CommentCustomStyles | {} | Granular custom styles/SX props for every UI element. | | classes | CommentClassNames | {} | Custom CSS classes for every UI element. | | labels | Partial<CommentLabels> | {} | Internationalization & custom text labels. | | renderers | CommentCustomRenderers<T> | {} | Custom slot overrides for avatar, header, body, actions, composer, empty state. | | onSubmitComment | (data) => Promise<void> \| void | undefined | Handler for submitting new comments / replies. | | onEditComment | (data) => Promise<void> \| void | undefined | Handler for editing a comment. | | onDeleteComment | (data) => Promise<void> \| void | undefined | Handler for deleting a comment. | | onReactComment | (data) => Promise<void> \| void | undefined | Handler for adding/removing an emoji reaction. | | onPinComment | (data) => Promise<void> \| void | undefined | Handler for pinning/unpinning comments. | | onReportComment | (data) => Promise<void> \| void | undefined | Handler for reporting a comment. | | formatDate | (date) => string | formatRelativeTime | Custom timestamp formatter function (e.g.,"2h ago"). | | sx | SxProps<Theme> | undefined | Root container MUIsx styling props. |


config Options (NestedCommentsConfig)

| Option | Type | Default | Description | | :--------------------- | :------------------------------------------------------ | :------------------------------------ | :------------------------------------------------------------------- | | enableNesting | boolean | true | Whenfalse, renders as simple one-by-one linear comments. | | maxDepth | number | Infinity | Maximum nesting depth level. | | showAvatars | boolean | true | Set tofalse to hide user images and photos. | | avatarShape | 'circle' \| 'rounded' \| 'square' | 'circle' | Shape of user avatars. | | showThreadLines | boolean | true | Whether to draw vertical connecting thread lines for nested replies. | | collapsible | boolean | true | Allow collapsing/expanding nested reply branches. | | defaultExpanded | boolean | true | Whether reply branches start expanded by default. | | enableReactions | boolean | true | Enable reaction pills and counts. | | quickReactions | string[] | ['👍','❤️','🔥','🎉','🚀','👀'] | List of quick emoji buttons. | | enableEmojiPicker | boolean | true | Enable popup emoji picker fromemoji-picker-react. | | composerPosition | 'top' \| 'bottom' \| 'both' \| 'none' | 'top' | Placement of the main comment input box. | | softDeleteHandling | 'placeholder' \| 'hide' | 'placeholder' | Keep deleted comments as placeholder or remove completely. | | showSortControl | boolean | true | Show sorting dropdown. | | sortBy | 'newest' \| 'oldest' \| 'mostUpvoted' \| 'mostReplies' | 'newest' | Initial or controlled sort order. | | minContentLength | number | 1 | Minimum characters for validation. | | maxContentLength | number | 5000 | Maximum characters for validation. |


🏗️ Publishing to NPM

# 1. Build the lightweight minified bundle (creates ESM, CJS, and .d.ts in dist/)
npm run build:lib

# 2. Lotgin to npm
npm login

# 3. Publish to npm registry
npm publish

📄 License

MIT © dot