# Typing Indicator

This example shows how to build a custom `TypingIndicator` based on the default.

## Best Practices

- Respect `typing_events` in channel config to avoid false indicators.
- Filter out the current user to prevent self-typing noise.
- Keep the indicator compact for busy channels and small screens.
- Avoid rendering long user lists; cap or summarize typers.
- Match the default dot animation timing for consistency.

## Create the Component

Using the `typing` object from `TypingContext`, you can access the `name` and `role` of users currently typing. The `threadList` prop lets you render in the main message list or at the bottom of a thread.

```tsx
export const CustomTypingIndicator = (props: TypingIndicatorProps) => {
  const { threadList } = props;

  const { channelConfig, thread } = useChannelStateContext();
  const { client } = useChatContext();
  const { typing = {} } = useTypingContext();

  if (channelConfig?.typing_events === false) {
    return null;
  }

  const typingInChannel = !threadList
    ? Object.values(typing).filter(
        ({ parent_id, user }) => user?.id !== client.user?.id && !parent_id,
      )
    : [];

  const typingInThread = threadList
    ? Object.values(typing).filter(
        ({ parent_id, user }) =>
          user?.id !== client.user?.id && parent_id === thread?.id,
      )
    : [];

  return (
    <div
      className={`str-chat__typing-indicator ${
        (threadList && typingInThread.length) ||
        (!threadList && typingInChannel.length)
          ? "str-chat__typing-indicator--typing"
          : ""
      }`}
    >
      <div className="str-chat__typing-indicator__avatars">
        {(threadList ? typingInThread : typingInChannel).map(({ user }, i) => (
          <div className="username">
            <div className="typing-indicator-name">{user?.name}</div>
            <div className="typing-indicator-role ">{user?.role}</div>
          </div>
        ))}
      </div>
      <div className="str-chat__typing-indicator__dots">
        <div className="str-chat__typing-indicator__dot" />
        <div className="str-chat__typing-indicator__dot" />
        <div className="str-chat__typing-indicator__dot" />
      </div>
    </div>
  );
};
```

```css
.str-chat__typing-indicator__dots {
  border: none;
  display: flex;
  margin-left: 0;
  width: fit-content;
}

.str-chat__typing-indicator__dot {
  background: var(--grey);
  opacity: 1;
  height: 4px;
  width: 4px;
  border-radius: var(--border-radius-round);
  display: flex;
}

.str-chat__typing-indicator__dot:nth-child(3) {
  opacity: 1;
}

.str-chat__typing-indicator__dot:nth-child(2) {
  opacity: 1;
}

.typing-indicator-name {
  font-weight: var(--font-weight-bold);
  color: var(--grey);
}
.typing-indicator-role {
  font-weight: var(--font-weight-regular);
  color: var(--grey-whisper);
  margin-left: var(--xxs-m);
}

.username {
  display: flex;
}
```

From here, all we need to do is override the default component in `Channel`:

```tsx
<Channel TypingIndicator={CustomTypingIndicator}>
  {/* children of Channel component */}
</Channel>
```

## The Result

![Custom Typing Indicator UI Component for Chat](@chat-sdk/react/v13/_assets/TypingIndicator.png)


---

This page was last updated at 2026-04-21T09:53:40.949Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v13/guides/customization/typing_indicator/](https://getstream.io/chat/docs/sdk/react/v13/guides/customization/typing_indicator/).