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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@alejotoro-o/chat-ui

v1.4.3

Published

This package provides a set of frontend components designed to help you quickly build modern, responsive chat interfaces. It focuses on flexibility, developer experience, and seamless integration with any backend.

Downloads

1,389

Readme

Chat UI

This package provides a set of frontend components designed to help you quickly build modern, responsive chat interfaces. It focuses on flexibility, developer experience, and seamless integration with any backend.

Key Features

  • Backend‑agnostic: Plug in any backend service via simple callbacks. The components don’t enforce a specific data source, making them compatible with REST APIs, WebSockets, GraphQL, Firebase, or custom infrastructures.

  • Tailwind CSS support: Built with Tailwind for clean, utility‑first defaults. Every component is fully customizable — override styles using Tailwind classes or apply your own custom CSS for complete control over the look and feel.

  • File handling: Out‑of‑the‑box support for sending and receiving files. Users can drag‑and‑drop, paste, or select files, and the UI provides previews for images and other file types.

  • Accessible & responsive: Components are designed with accessibility and responsiveness in mind, ensuring a smooth experience across devices and screen sizes.

  • Composable architecture: Each piece (Chat, ChatHeader, MessageList, MessageBar, etc.) is modular. You can use them together for a full chat app or individually to fit into existing layouts.

Installation

Install the package via npm:

npm install @alejotoro-o/chat-ui

Requirements

  • React 19+ and React DOM 19+ are required as peer dependencies. Make sure your project is using compatible versions:
npm install react@^19.1.0 react-dom@^19.1.0
  • Tailwind CSS must be configured in your project. The components rely on Tailwind utilities for styling.

Tailwind Configuration

Update your tailwind.config.js to include the package so styles are applied correctly:

const config = {
  content: [
    // Your app sources
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',

    // Include chat-ui components
    './node_modules/@alejotoro-o/chat-ui/dist/*.{js,jsx,ts,tsx}',
  ],
  // Rest of your Tailwind config...
};

export default config;

Notes

  • The package ships with ESM exports (type: "module") and provides both JavaScript and TypeScript definitions (dist/index.js and dist/index.d.ts).
  • Styling utilities use clsx and tailwind-merge internally, so you can safely combine and override classes.

Once installed and configured, you can start importing components like:

import { Chat, ChatHeader, MessageList, MessageBar } from '@alejotoro-o/chat-ui';

Usage

This package allows you to build a chat UI in a modular fashion. Each component is highly extensible and customizable, so you can compose them together to create a full chat interface or use them individually in existing layouts.

Below is a minimal example showing how to wire up the components with local state. For a more complete demo, check out App.tsx in the dev folder.

type ChatMessage = {
    text?: string;
    files?: { name: string; url: string; type: string }[];
    sender: "UserA" | "UserB";
    timestamp: Date;
};

const sendMessage = (payload: { text?: string; files?: File[] }, sender: "UserA" | "UserB") => {
    const fileObjs = payload.files?.map((file) => ({
        name: file.name,
        type: file.type,
        url: URL.createObjectURL(file),
    }));

    setMessages((prev) => [
        ...prev,
        {
            text: payload.text,
            files: fileObjs,
            sender,
            timestamp: new Date(),
        },
    ]);
};

const deleteChat = () => {
    console.log("Chat deleted");
    setMessages([]);
};

const clearChat = () => {
    console.log("Chat cleared");
    setMessages([]);
};

<Chat>
    <ChatHeader
        name="User A"
        status="Online"
        options={[
            { label: "Clear Chat", onClick: clearChat },
            { label: "Delete Chat", onClick: deleteChat, destructive: true },
        ]}
    />
    <MessageList>
        {messages.map((msg, idx) => {
            const prevMsg = idx > 0 ? messages[idx - 1] : null;
            const prevDate = prevMsg ? formatDate(prevMsg.timestamp) : null;
            const currDate = formatDate(msg.timestamp);

            return (
                <React.Fragment key={idx}>
                    {prevDate !== currDate && <DateDivider date={msg.timestamp} />}
                    <Message
                        text={msg.text}
                        files={msg.files}
                        isMe={msg.sender === "UserA"}
                        timestamp={msg.timestamp}
                    />
                </React.Fragment>
            );
        })}
    </MessageList>
    <MessageBar
        onSend={(payload) => sendMessage(payload, "UserA")}
    />
</Chat>

How it works

  • Chat: Main wrapper that defines the chat layout.
  • ChatHeader: Displays the chat title, status, and optional actions (e.g., clear/delete).
  • MessageList: Scrollable container for messages.
  • DateDivider: Separates messages by date.
  • Message: Renders individual messages, aligned left/right based on isMe.
  • MessageBar: Input area for sending text and files.

Customization

  • Override styles using Tailwind classes or custom CSS.
  • Extend functionality by passing callbacks (onSend, onClick, etc.) to integrate with any backend.
  • File support is built in, drag‑and‑drop, paste, or select files directly in the message bar.

Launch Development Environment

The development environment provides an interactive playground where you can explore, preview, and test all chat UI components in real time. It’s designed to make iteration easy, so you can quickly validate layout changes, props, and new features such as avatars, unread badges, and truncation behavior.

Development Environment Screenshot

Steps to get started

  1. Clone the repository

    git clone https://github.com/alejotoro-o/chat-ui.git
  2. Navigate into the project folder

    cd chat-ui
  3. Install dependencies

    npm install
  4. Run the development server

    npm run dev
  5. Open the environment in your browser: By default, the server runs at http://localhost:5173/. You’ll see the component gallery with live previews.

What you can do here

  • Browse all available components side by side.
  • Test components props.
  • Validate responsive behavior (flex layouts, truncation, scrollable lists).
  • Experiment with designs and Tailwind classes.

Components Overview

This package provides the following components:

Chat

The Chat component is the main wrapper for a chat interface. It defines the layout and contains the header, message list, and input bar.

type ChatProps = {
    children: React.ReactNode
    className?: string
}
  • children: React nodes to render inside the chat (header, list, bar).
  • className: Optional Tailwind/custom classes to style the Chat container.

ChatHeader

The ChatHeader component displays the chat title, avatar, status, and an optional action menu.

type ChatHeaderOption = {
    label: string;
    onClick: () => void;
    destructive?: boolean; // optional flag for styling (e.g. red text for delete)
};

type ChatHeaderProps = {
    name: string;
    onClick?: () => void;
    avatar?: boolean;
    imageUrl?: string;
    status?: string;
    className?: string;
    options?: ChatHeaderOption[]
};
  • name: Display name of the chat or contact.
  • onClick: Optional callback to perform an action when the user’s profile is clicked.
  • avatar: Enables/disables avatar rendering.
    • If true and imageUrl is provided, the avatar image is shown.
    • If true and imageUrl is not provided, a fallback avatar is displayed.
    • If false, no avatar is rendered.
  • imageUrl: Optional avatar image source URL.
  • status: Presence text (e.g., “Online”, “Typing…”).
  • className: Optional styles for the header container.
  • options: Array of actions with label, onClick, and optional destructive flag.

Message

The Message component renders a single message bubble with optional text, files, and timestamp. Alignment is controlled by the isMe flag.

type MessageProps = {
    text?: string;
    files?: { name: string; url: string; type: string }[];
    isMe: boolean;
    timestamp: Date;
    status?: "sending" | "sent" | "delivered" | "read";
    classNameMe?: string;
    textColorMe?: string;
    classNameOther?: string;
    textColorOther?: string;
    classNameRead?: string;
    className?: string;
};
  • text: Message text content.
  • files: Array of file attachments with preview URLs.
  • isMe: Whether the message belongs to the current user.
  • timestamp: Date object used for display and grouping.
  • status: Current delivery state of the message.
    • "sending": Message is being sent.
    • "sent": Message successfully sent.
    • "delivered": Message has been received by the recipient.
    • "read": Recipient has opened the chat and seen the message.
  • classNameMe / textColorMe: Styles for the “me” bubble and text.
  • classNameOther / textColorOther: Styles for the “other” bubble and text.
  • classNameRead: Styles applied when the message status is "read".
  • className: Styles for the outer wrapper.

MessageList

The MessageList component is a scrollable container for messages and date dividers.

type MessageListProps = {
    children: React.ReactNode;
    className?: string;
    classNameScrollButton?: string;
};
  • children: Messages and related helpers (e.g., DateDivider).
  • className: Styles for the list container.
  • classNameScrollButton: Styles for the scroll-to-bottom button.

MessageBar

The MessageBar component provides an input area for sending messages and files.

type MessageBarProps = {
    onSend: (payload: { text?: string; files?: File[] }) => void;
    placeholder?: string;
    className?: string;
    allowFiles?: boolean;
    allowedFiles?: string;
    maxFiles?: number;
    maxFileSize?: number;
    errorMessage?: {
        invalidType?: string;
        maxFiles?: string;
        maxSize?: string;
    };
    classNameAttachIcon?: string;
    classNameSendIcon?: string;
};
  • onSend: Callback invoked with text and/or files when the user sends.
  • placeholder: Input placeholder text.
  • className: Styles for the bar container.
  • allowFiles: Enables file selection/drag‑and‑drop if true.
  • allowedFiles: A comma‑separated string of accepted file types for validation. Supports MIME types (e.g., application/pdf), MIME globs (e.g., image/*), or file extensions (e.g., .jpg, .png).
  • maxFiles: Maximum number of files that can be attached in one message. If exceeded, the component will display an error.
  • maxFileSize: Maximum size (in MB) allowed per file. Files larger than this will trigger an error.
  • errorMessage: Object containing custom string messages for file validation failures:
    • invalidType: Message shown when a file’s type or extension is not allowed.
    • maxFiles: Message shown when the file limit is exceeded.
    • maxSize: Message shown when a file exceeds the maximum size.
  • classNameAttachIcon: Styles for the attachment icon.
  • classNameSendIcon: Styles for the send icon.

ChatItem

The ChatItem component represents a row in a chat list, showing name, last message, date, avatar, and an options menu.

type ChatItemOptions = {
    label: string;
    onClick: () => void;
    destructive?: boolean; 
};

type ChatItemProps = {
    id: string;
    name: string;
    lastMessage: string;
    lastMessageStatus?: "sending" | "sent" | "delivered" | "read";
    date: Date;
    onClick: (id: string) => void;
    avatar?: boolean,
    imageUrl?: string;
    unreadCount?: number;
    options?: ChatItemOptions[];
    classNameRead?: string;
    classNameOptions?: string;
    classNameUnreadCount?: string;
    classNameUnreadDate?: string;
    className?: string;
};
  • id: Unique identifier passed to onClick.
  • name: Chat or contact name.
  • lastMessage: Preview of the most recent message.
  • status: Current delivery state of the last message sent.
    • "sending": Message is being sent.
    • "sent": Message successfully sent.
    • "delivered": Message has been received by the recipient.
    • "read": Recipient has opened the chat and seen the message.
  • date: Date of the last activity.
  • onClick: Handler invoked when the item is clicked.
  • avatar: Enables/disables avatar rendering.
    • If true and imageUrl is provided, the avatar image is shown.
    • If true and imageUrl is not provided, a fallback avatar is displayed.
    • If false, no avatar is rendered.
  • imageUrl: Optional avatar image URL.
  • unreadCount: Number of unread messages. If greater than zero, a badge is displayed.
  • options: Array of actions for the overflow menu (e.g., clear chat, delete chat).
  • classNameRead: Custom styles applied to the read status in the last message sent.
  • classNameOptions: Custom styles applied to the options menu container and items.
  • classNameUnreadCount: Custom styles applied to the unread badge (circle with count).
  • classNameUnreadDate: Custom styles applied to the date element when there are unread messages.
  • className: Custom styles for the list item wrapper.

ChatList

The ChatList component is a container for multiple ChatItem entries.

type ChatListProps = {
    children: React.ReactNode
    className?: string
}
  • children: One or more ChatItem elements.
  • className: Styles for the list container.

DateDivider

The DateDivider component separates messages by date with a label and horizontal lines.

type DateDividerProps = {
    date: Date
    locale?: string
    className?: string
    classNameLines?: string
    classNameText?: string
}
  • date: Date object to display as the divider label.
  • locale: Locale string used for date formatting.
  • className: Styles for the divider container.
  • classNameLines: Styles for the horizontal lines.
  • classNameText: Styles for the center date label.

Here’s a polished Utilities section in Markdown, with a short explanation and prop descriptions for formatDate. Ready for copy‑paste into your README:

Utilities

formatDate

A helper function to format a Date object into a short, human‑readable string (day, month, year only). Useful for rendering timestamps in messages or dividers.

// Utility to format just the date (no time)
export const formatDate = (date: Date, locale: string = "en-US") =>
    date.toLocaleDateString(locale, {
        day: "2-digit",
        month: "short",
        year: "numeric",
    });

Parameters

  • date: A JavaScript Date object to format.
  • locale: Optional locale string (default "en-US"). Determines language and formatting style.

Example

formatDate(new Date()); 
// "26 Nov 2025" (depending on locale)