A composable chat container with auto-scroll, animated messages, empty state, scroll-to-bottom button, and divider support.
Note: For rendering individual messages with avatars, bubble styling, and
timestamps, check out the Message Bubble
component — it's designed to work seamlessly inside ChatContainerMessage.
Installation
Usage
How It Works
ChatContainerwraps everything in a double-ring card shell with aScrollAreaviewport internally tracked viaviewportRef.- Auto-scroll: when
autoScrollistrue(default), the viewport scrolls to the bottom whenever a new message is registered — but only if the user was already at the bottom. ChatContainerMessagecallsregisterMessage()on mount and unregisters on unmount, keeping an internalmessageCountthat powers empty-state detection and auto-scroll triggers.ChatContainerEmptyStaterenders only whenmessageCount === 0, animating in/out with a fade+slide.ChatContainerScrollButtonfloats above the scroll area and appears with anAnimatePresencetransition whenever the user scrolls up past thebottomThreshold.ChatContainerDividerrenders a full-width horizontal rule with an optional centred label (e.g. "Today").
API Reference
ChatContainer
| Prop | Type | Default |
|---|---|---|
bottomThreshold? | number | 64 |
autoScroll? | boolean | true |
children | React.ReactNode | - |
ChatContainerContent
Centres and pads its children. Pass className to override max-w-3xl or spacing.
ChatContainerEmptyState
| Prop | Type | Default |
|---|---|---|
title? | string | "No messages yet" |
description? | string | "Start a conversation to see messages here." |
icon? | React.ReactNode | - |
ChatContainerMessage
Wraps each individual message. Animates in with a fade + upward slide and registers itself with the container context so auto-scroll and empty-state detection work correctly.
ChatContainerScrollButton
Floats over the bottom of the scroll area, visible only when the user has scrolled away from the bottom. Clicking it smooth-scrolls to the latest message. Accepts all Button props plus an optional icon override.
ChatContainerDivider
| Prop | Type | Default |
|---|---|---|
label? | string | - |
useChatContainer
Hook that exposes the container context: scrollToBottom, isAtBottom, isEmpty, messageCount, registerMessage. Must be called inside a <ChatContainer />.