import { useEffect } from "react";
import {
type TypingIndicatorProps,
useChannelStateContext,
useChatContext,
useTypingContext,
} from "stream-chat-react";
export const CustomTypingIndicator = ({
isMessageListScrolledToBottom = true,
scrollToBottom,
threadList,
}: TypingIndicatorProps) => {
const { channelConfig, thread } = useChannelStateContext();
const { client } = useChatContext();
const { typing = {} } = useTypingContext();
const typingUsers = Object.values(typing).filter(({ parent_id, user }) => {
if (user?.id === client.user?.id) return false;
if (threadList) return parent_id === thread?.id;
return !parent_id;
});
useEffect(() => {
if (typingUsers.length > 0 && isMessageListScrolledToBottom) {
scrollToBottom();
}
}, [isMessageListScrolledToBottom, scrollToBottom, typingUsers.length]);
if (channelConfig?.typing_events === false) return null;
if (!typingUsers.length || !isMessageListScrolledToBottom) return null;
return (
<div className="custom-typing-indicator">
<span>{typingUsers.map(({ user }) => user?.name).join(", ")}</span>
<span className="custom-typing-indicator__dots">...</span>
</div>
);
};This is beta documentation for Stream Chat React SDK v14. For the latest stable version, see the latest version (v13)
.
Typing Indicator
This example shows how to build a custom message-list TypingIndicator based on the current v14 prop contract.
Best Practices
- Respect
typing_eventsin channel config so you do not show typing UI when the feature is disabled. - Filter out the current user from typing results.
- Keep the message-list typing indicator and header typing indicator separate.
- Preserve the
scrollToBottombehavior if you want the list to stay pinned while typing. - Summarize or cap typing users in busy channels.
Create The Component
The message-list TypingIndicator now receives scrollToBottom, optional isMessageListScrolledToBottom, and threadList.
.custom-typing-indicator {
display: flex;
align-items: center;
gap: 8px;
color: #6b7280;
}Register The Override
TypingIndicator is a ComponentContext override in v14, so register it with WithComponents:
import {
Channel,
MessageInput,
MessageList,
Thread,
WithComponents,
} from "stream-chat-react";
const App = () => (
<WithComponents overrides={{ TypingIndicator: CustomTypingIndicator }}>
<Channel>
<MessageList />
<MessageInput />
<Thread />
</Channel>
</WithComponents>
);Header Typing Indicators
If you want typing state in a custom ChannelHeader or ThreadHeader, render TypingIndicatorHeader there instead of reusing the message-list TypingIndicator.