UI Blocks
Reusable React blocks for Chatpack chat experiences.
Browse layouts, input controls, realtime status, group tools, and message primitives from @chatpack/ui. Previews use sample content. Connected components need a ChatpackUIProvider and a client in your app.
Composed chat UIs
42 UI blocks
Install
pnpm add @chatpack/ui @chatpack/clientImport the stylesheet once, then provide a React-enabled client and the viewer id. User ids are opaque to Chatpack, so applications can render their own profiles:
import { createChatClient } from "@chatpack/client/react";
import { ChatpackUIProvider, ChatWindow } from "@chatpack/ui";
import "@chatpack/ui/styles.css";
const client = createChatClient({ baseURL: "/", basePath: "/api/chat" });
export function Chat({ conversationId, userId }: { conversationId: string; userId: string }) {
return (
<ChatpackUIProvider client={client} userId={userId} renderUser={(id) => <span>{id}</span>}>
<ChatWindow conversationId={conversationId} />
</ChatpackUIProvider>
);
}Current Blocks
Layout
ConversationList, CompactChatList, ConversationHeader, ConversationRow,
MessageThread, FlatMessageThread, GroupedMessageThread, MessageRow,
ChatWindow, InboxLayout, MobileChatSheet, FloatingChatWidget,
AssistantThread, JumpToLatest
Input
MessageComposer, ReplyComposer, MentionComposer, MentionAutocomplete,
ChatComposerBar, MessageActions, ForwardDialog, MessageSearch,
MessageSearchResults, ChatCommandPalette, StartDirectMessage,
NewGroupForm, QuickReactions, MessageReactions
Realtime
TypingIndicator, TypingDots, ConnectionStatus, PresenceBar,
PresenceAvatarStack, PresenceIndicator, OnlineStatusChip, ReadReceipts,
UnreadInbox, MarkReadButton
Groups
MembersList, ParticipantManager, InviteManager, InviteAccept,
JoinRequests, ChannelDirectory, ChannelSettings, LeaveGroup
Moderation
BlockedUsers, MuteToggle, MutedList, ReportDialog, ModerationQueue,
BanManager
Media
AttachmentComposer, AttachmentDropzone, MessageAttachments, ImageBubble,
FileBubble, UploadProgress, AttachmentGallery, UnavailableAttachment
Primitives
UserAvatarUnreadBadge, ChatPrimitives, MessageBubble, Timestamp,
PresenceDot, ReadReceiptTicks, ReactionPill, ReplyQuoteBar,
ForwardedLabel, MentionChip, RoleTag, ErrorNotice, SystemMessage,
SoftDeletedTombstone, EmptyInbox, EmojiPicker
All data comes from the public client hooks and actions. Realtime blocks do not implement their own reconnect or polling logic, and reactions are never copied into component state.
The gallery highlights 42 exported components. The full list above covers the package. Blocks that depend on host policy accept callbacks instead of embedding authentication or user-database assumptions.
Connected block contract
Configure one React client at module scope and pass it to
ChatpackUIProvider. The provider owns only the opaque viewer id and profile
renderer. It does not create users, authenticate requests, or invent profile
fields.
import { createChatClient } from "@chatpack/client/react";
import { ChatpackUIProvider, ChatWindow } from "@chatpack/ui";
import "@chatpack/ui/styles.css";
const client = createChatClient({ baseURL: "/", basePath: "/api/chat" });
export function Chat({ conversationId, userId }: { conversationId: string; userId: string }) {
return (
<ChatpackUIProvider client={client} userId={userId} renderUser={(id) => <span>{id}</span>}>
<ChatWindow conversationId={conversationId} />
</ChatpackUIProvider>
);
}Message actions call messages.edit, messages.delete, messages.react,
messages.unreact, and messages.forward. Ownership is checked before edit
and delete controls render; core remains the final authorization boundary.
MessageComposer sends on Enter, preserves Shift+Enter, and throttles typing
signals to one start action per three seconds. Message lists reverse the
client's newest-first page for display and call markRead for the newest item.
Group, channel, invite, join-request, and moderation blocks call their typed client actions. They do not accept fake report, mute, member, or channel arrays. Host callbacks remain for profile rendering, navigation, and success handling.
Filepack attachments
Media metadata contains only id, name, contentType, and size. It never
contains a URL. Configure @chatpack/file in the host and pass its authorized
resolveTarget implementation to ImageBubble, FileBubble,
MessageAttachments, or AttachmentGallery. A missing or failed target shows
the unavailable state. UI must not call Chatpack routes directly or expose
long-lived storage URLs.
Public API quick reference
The blocks are small compositions around the public client. The props below are the main integration points; the TypeScript declarations remain the complete reference.
Connected layout and input blocks
| Block | Main props |
|---|---|
ConversationList | selectedId?, onSelect?, className?, renderUser? |
MessageThread | conversationId, onReply?, className?, showHeader?, onEmptyAction?, renderUser? |
ChatWindow | conversationId, className? |
MessageComposer | conversationId, replyTo?, disabled?, placeholder?, onSent?, onClearReply? |
ConnectionStatus | No props; reads the client's realtime status |
MessageActions | message, canEdit?, onReply?, onForward?, onComplete? |
MessageSearch | onSelect? |
QuickReactions | message |
ConversationList passes the selected ClientConversation to onSelect.
MessageThread passes the selected ClientMessage to onReply. The composed
blocks CompactChatList, FlatMessageThread, GroupedMessageThread,
InboxLayout, MobileChatSheet, FloatingChatWidget, and AssistantThread
wrap these connected blocks and preserve their client-backed behavior.
Realtime, groups, and moderation
| Block | Main props |
|---|---|
TypingIndicator, TypingDots | conversationId |
PresenceIndicator, OnlineStatusChip | userId |
PresenceBar, PresenceAvatarStack | userIds |
ReadReceipts | conversationId, messageSeq |
UnreadInbox | conversationId, onSelect? |
MarkReadButton | conversationId, messageId |
ParticipantManager, JoinRequests | conversationId, renderUser? |
InviteManager, ChannelSettings, MuteToggle | conversationId |
InviteAccept | code, onAccepted? |
ChannelDirectory | onJoined? |
LeaveGroup | conversationId, onLeft? |
ReportDialog | targetType, targetId, onDone? |
BlockedUsers, MutedList | renderUser? |
These blocks use typed client actions for conversations, invites, channels, join requests, moderation, and participant changes. The host still owns authentication, profile rendering, navigation, and any success or error workflow outside the block.
Theme
Import styles.css for the package defaults. Override a subtree with
ChatpackUIThemeProvider when the host needs a small token adjustment:
import { ChatpackUIThemeProvider, ChatWindow } from "@chatpack/ui";
<ChatpackUIThemeProvider theme={{ accent: "#2563eb", accentContrast: "#ffffff", radius: "1rem" }}>
<ChatWindow conversationId={conversationId} />
</ChatpackUIThemeProvider>;Theme keys include surface, panel, sidebar, border, input, text,
muted, mutedSurface, accent, accentContrast, highlight,
highlightContrast, secondary, secondaryContrast, bubbleOwn,
bubbleOwnMuted, bubbleOwnContrast, bubbleOther, destructive, online,
mentionRing, controlShadow, panelShadow, dialogShadow, subtleShadow,
and radius.
Replies and threads
MessageComposer.replyTo and ReplyQuoteBar describe a reply to one message.
They do not replace a full threaded-replies surface. A threaded UI still needs
root-message identity, thread pagination, unread state, and navigation. Use the
client thread APIs and app-owned routing or panels for those surfaces until a
dedicated thread block is exported.