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_events in 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 scrollToBottom behavior 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.

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>
  );
};
.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.