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>
);
};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
TypingIndicatorHeaderfor header subtitle typing state, not the message-listTypingIndicator. - Keep the header layout light because it rerenders with channel and typing updates.
- Preserve a sidebar toggle if your layout depends on
ChannelListon 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:
.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>
);