@investtal/ui-chat-message-box
v2.0.1
Published
Complete chat system with message input and display components for messaging applications.
Downloads
229
Readme
@ivtui/chat-message-box
Complete chat system with message input and display components for messaging applications.
Features
Message Input (ChatMessageBox)
- 📝 Minimal TipTap editor for text input
- 😊 Emoji picker integration
- 📎 File attachment support
- 🎤 Voice recording
- @ Mentions with autocomplete
- / Slash commands
- ⌨️ Keyboard shortcuts (Enter to send)
Message Display (New!)
- 💬 Message bubbles with sender alignment
- 👤 Avatars and sender names
- 🕐 Timestamps with date formatting
- ✓ Message status indicators (sending, sent, delivered, read, failed)
- 📅 Date separators (Today, Yesterday, dates)
- 📦 Automatic message grouping
- 📜 Auto-scroll with scroll detection
- 🎨 Tailwind CSS styling
Installation
bun add @ivtui/chat-message-boxComponents
1. Chat (All-in-One Solution)
Complete chat interface combining message list and input box.
import { Chat } from "@ivtui/chat-message-box"
import type { ChatMessage } from "@ivtui/chat-message-box"
function ChatApp() {
const [messages, setMessages] = useState<ChatMessage[]>([
{
id: "1",
content: "Hello!",
sender: { id: "user-2", name: "Jane", avatar: "..." },
timestamp: new Date(),
status: "read",
},
])
const handleSend = (text: string, html: string) => {
const newMessage: ChatMessage = {
id: Date.now().toString(),
content: text,
sender: { id: "user-1", name: "Me" },
timestamp: new Date(),
status: "sending",
}
setMessages([...messages, newMessage])
}
return (
<div style={{ height: "600px" }}>
<Chat
messages={messages}
currentUserId="user-1"
onSendMessage={handleSend}
/>
</div>
)
}2. MessageList (Message Display Only)
Display messages without input box.
import { MessageList } from "@ivtui/chat-message-box"
import type { ChatMessage } from "@ivtui/chat-message-box"
function Messages() {
return (
<MessageList
messages={messages}
currentUserId="user-1"
isLoading={false}
/>
)
}3. Message (Single Message Bubble)
import { Message } from "@ivtui/chat-message-box"
function SingleMessage() {
return (
<Message
message={{
id: "1",
content: "Hello!",
sender: { id: "user-1", name: "John" },
timestamp: new Date(),
status: "sent",
isCurrentUser: true,
}}
showAvatar={true}
showSenderName={true}
showTimestamp={true}
/>
)
}4. ChatMessageBox (Input Only)
import { ChatMessageBox } from "@ivtui/chat-message-box"
function ChatInput() {
const handleSend = (text: string, html: string) => {
console.log("Message:", text)
}
return (
<ChatMessageBox
onSend={handleSend}
placeholder="Type a message..."
/>
)
}Types
ChatMessage
interface ChatMessage {
id: string
content: string
sender: ChatUser
timestamp: Date | string
status?: MessageStatus // "sending" | "sent" | "delivered" | "read" | "failed"
type?: MessageType // "text" | "image" | "file" | "voice" | "system"
isCurrentUser?: boolean
replyTo?: string // For future reply feature
}ChatUser
interface ChatUser {
id: string
name: string
avatar?: string
}Chat Props
interface ChatProps {
messages: ChatMessage[]
currentUserId: string
onSendMessage: (text: string, html: string) => void
isLoading?: boolean
onLoadMore?: () => void
messageBoxProps?: Partial<ChatMessageBoxProps>
className?: string
emptyState?: React.ReactNode
}Real-time Chat Integration
WebSocket Example
import { Chat } from "@ivtui/chat-message-box"
import { useEffect, useState } from "react"
function RealtimeChat() {
const [messages, setMessages] = useState<ChatMessage[]>([])
const [ws, setWs] = useState<WebSocket | null>(null)
useEffect(() => {
const socket = new WebSocket("ws://your-server.com/chat")
socket.onmessage = (event) => {
const newMessage = JSON.parse(event.data)
setMessages(prev => [...prev, newMessage])
}
setWs(socket)
return () => socket.close()
}, [])
const handleSend = (text: string, html: string) => {
const message: ChatMessage = {
id: `temp-${Date.now()}`,
content: text,
sender: { id: "me", name: "Me" },
timestamp: new Date(),
status: "sending",
}
setMessages(prev => [...prev, message])
ws?.send(JSON.stringify(message))
}
return (
<div style={{ height: "100vh" }}>
<Chat
messages={messages}
currentUserId="me"
onSendMessage={handleSend}
/>
</div>
)
}Optimistic Updates
const handleSend = async (text: string) => {
const tempId = `temp-${Date.now()}`
// Add optimistic message
const optimisticMessage: ChatMessage = {
id: tempId,
content: text,
sender: currentUser,
timestamp: new Date(),
status: "sending",
}
setMessages(prev => [...prev, optimisticMessage])
try {
// Send to server
const response = await fetch("/api/messages", {
method: "POST",
body: JSON.stringify({ content: text }),
})
const serverMessage = await response.json()
// Update with server data
setMessages(prev =>
prev.map(msg =>
msg.id === tempId ? { ...serverMessage, status: "sent" } : msg
)
)
} catch (error) {
// Mark as failed
setMessages(prev =>
prev.map(msg =>
msg.id === tempId ? { ...msg, status: "failed" } : msg
)
)
}
}Message Features
Status Indicators
// Messages automatically show status icons for current user
{
status: "sending" // Clock icon, gray
status: "sent" // Single check, gray
status: "delivered" // Double check, gray
status: "read" // Double check, blue
status: "failed" // Warning icon, red
}Date Separators
Automatically inserted between messages from different days:
- Today - "Today"
- Yesterday - "Yesterday"
- This year - "Jan 15"
- Other years - "Jan 15, 2024"
Message Grouping
Consecutive messages from the same sender are automatically grouped:
- First message: Shows avatar, sender name, timestamp
- Middle messages: Hidden avatar/name/timestamp
- Last message: Shows avatar, timestamp
Utilities
import {
formatMessageTime, // Format time as "14:30"
formatDateSeparator, // Format date as "Today" / "Yesterday" / date
isSameDay, // Check if two dates are same day
} from "@ivtui/chat-message-box"Voice Recording
The component includes Facebook Messenger-style voice recording. See VOICE_RECORDING_API.md for details.
Future Features (Planned)
- Virtual scrolling for thousands of messages
- Infinite scroll with lazy loading
- Typing indicators
- Reply to messages
- File message previews
- Image message rendering
- Voice message playback
- Message reactions
- Read receipts with avatars
Storybook
Run Storybook to see all components and examples:
bun run storybookStories available:
Chat/Chat- Full chat interfaceChat/Message- Individual message bubbles
Styling
The package uses Tailwind CSS for styling. Make sure Tailwind is configured in your project.
For custom styling, you can override classes via the className prop on any component.
