This is beta documentation for Stream Chat React SDK v14. For the latest stable version, see the latest version (v13) .

Channel Header

This example shows how to render a custom ChannelHeader.

Unlike SDK-owned UI surfaces that are replaced through WithComponents, a custom channel header is usually just rendered in place of the default ChannelHeader.

Best Practices

  • Pull channel display data from hooks such as useChannelPreviewInfo() instead of duplicating it.
  • Use TypingIndicatorHeader for header subtitle typing state, not the message-list TypingIndicator.
  • Keep the header layout light because it rerenders with channel and typing updates.
  • Preserve a sidebar toggle if your layout depends on ChannelList on smaller screens.
  • Prefer your own custom class names over older SDK-specific header class names.

Implementation

The default header derives the title and image from the current channel and swaps its subtitle between typing state and online/member status. A custom header can reuse the same data:

import {
  ChannelAvatar,
  TypingIndicatorHeader,
  useChannelPreviewInfo,
  useChannelStateContext,
  useTypingContext,
} from "stream-chat-react";

const CustomChannelHeader = () => {
  const { channel, channelConfig } = useChannelStateContext();
  const { typing = {} } = useTypingContext();
  const { displayImage, displayTitle, groupChannelDisplayInfo } =
    useChannelPreviewInfo({ channel });

  const hasTyping =
    channelConfig?.typing_events !== false &&
    Object.values(typing).some(({ parent_id }) => !parent_id);

  return (
    <div className="custom-channel-header">
      <ChannelAvatar
        displayMembers={groupChannelDisplayInfo?.members}
        imageUrl={displayImage}
        overflowCount={groupChannelDisplayInfo?.overflowCount}
        size="lg"
        userName={displayTitle}
      />
      <div className="custom-channel-header__content">
        <div className="custom-channel-header__title">{displayTitle}</div>
        <div className="custom-channel-header__subtitle">
          {hasTyping ? <TypingIndicatorHeader /> : "Custom subtitle"}
        </div>
      </div>
    </div>
  );
};
.custom-channel-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
}

.custom-channel-header__content {
  min-width: 0;
}

.custom-channel-header__title {
  font-weight: 600;
}

.custom-channel-header__subtitle {
  color: #6b7280;
  font-size: 0.875rem;
}

Final Code

Render your custom header where you would normally place ChannelHeader:

import {
  Channel,
  ChannelList,
  Chat,
  MessageInput,
  MessageList,
  Thread,
  Window,
} from "stream-chat-react";

const App = () => (
  <Chat client={chatClient}>
    <ChannelList />
    <Channel>
      <Window>
        <CustomChannelHeader />
        <MessageList />
        <MessageInput />
      </Window>
      <Thread />
    </Channel>
  </Chat>
);