import { Channel, MessageList, WithComponents } from "stream-chat-react";
const App = () => (
<WithComponents overrides={{ TypingIndicator: CustomTypingIndicator }}>
<Channel>
<MessageList />
</Channel>
</WithComponents>
);Indicators
The React Chat SDK includes loading, empty-state, pagination, and typing indicators for channel, message, and thread surfaces.
Best Practices
- Keep loading and empty states lightweight so they do not cause layout jumps.
- Reuse the SDK pagination primitives unless you need custom loading behavior.
- Treat the message-list typing indicator and header typing indicator as separate surfaces.
- Override shared indicators with
WithComponentswhen you want consistent UI across nested SDK components. - Audit custom indicator CSS against the current DOM before carrying older selectors forward.
Available Components
EmptyStateIndicatorLoadingChannelsLoadingErrorIndicatorLoadingIndicatorLoadMoreButtonLoadMorePaginatorTypingIndicatorTypingIndicatorHeader
UI Customization
EmptyStateIndicator
Use a local prop where the parent component still exposes one, or register a shared override with WithComponents.
Common surfaces:
ChannelListMessageListThreadChatView.ThreadAdapter
LoadingErrorIndicator
Customize the loading error surface for Channel or other loading flows that expose it.
LoadingIndicator
Customize generic loading states used while querying or paginating.
LoadMorePaginator And LoadMoreButton
Use Paginator on ChannelList when you want infinite scroll or a different load-more experience.
TypingIndicator
TypingIndicator is the message-list and thread-list typing surface. It renders avatar stacks plus animated dots and accepts the current scroll-related props:
scrollToBottomisMessageListScrolledToBottomthreadList
See the Examples section below for an override example.
TypingIndicatorHeader
TypingIndicatorHeader is the inline header subtitle surface used by ChannelHeader and ThreadHeader. It is not a ComponentContext override. If you build a custom channel or thread header, render TypingIndicatorHeader yourself.
EmptyStateIndicatorProps
| Prop | Description | Type |
|---|---|---|
listType | Type of list that will display the indicator. | "channel" | "message" | "thread" |
LoadingErrorIndicatorProps
| Prop | Description | Type |
|---|---|---|
error | Error object rendered by the indicator. | Error |
LoadingIndicatorProps
| Prop | Description | Type |
|---|---|---|
color | Indicator color. Defaults to #006CFF. | string |
size | Indicator size. Defaults to 15. | number |
LoadMoreButtonProps
| Prop | Description | Type |
|---|---|---|
onClick | Callback used to load the next page. | React.MouseEventHandler<HTMLButtonElement> |
refreshing | Legacy loading flag for the button. Prefer isLoading where applicable. | boolean |
LoadMorePaginatorProps
| Prop | Description | Type |
|---|---|---|
hasNextPage | Whether another page is available. | boolean |
LoadMoreButton | Custom button component for pagination. Defaults to LoadMoreButton. | component |
loadNextPage | Callback used to load the next page. | () => void |
refreshing | Legacy paginator loading flag. | boolean |
reverse | Whether the load-more button should appear at the top instead of the bottom. | boolean |
TypingIndicatorProps
| Prop | Description | Type |
|---|---|---|
isMessageListScrolledToBottom | Optional flag that suppresses the indicator when the list is scrolled away from the latest message. | boolean |
scrollToBottom | Callback used by the default indicator to keep the list pinned to the latest message while typing. | () => void |
threadList | When true, the indicator filters typing state for the current thread instead of the channel. | boolean |