Avatars
The avatar components draw a user, a channel, or a group of users as a circle. They're the building blocks of the avatars in the channel list, the message list, threads, polls and channel details, and you can render them in your own UI. Every component on this page is exported from stream-chat-react-native and stream-chat-expo.
Best practices
- Render
UserAvatarfor a user andChannelAvatarfor a channel. They pick the image, the initials, the background color and the accessibility label.Avataris the base they share, for content of your own. - Every avatar reads the theme, which
OverlayProviderandChatprovide.ChannelAvataralso reads the chat client, so render it insideChat. - To change the avatar of every channel list row, override
ChannelPreviewAvatar. It's the only override key whose default is one of these components. Elsewhere, override the part that renders the avatar, such asMessageAuthor,MessageRepliesAvatarsorMessageUserReactionsAvatar. UserAvatardoesn't readuser.online. Pass it asshowOnlineIndicator, as the SDK does.
Available components
| Component | What it shows | Where the SDK renders it |
|---|---|---|
Avatar |
An image in a circle, or a placeholder | Inside the other avatars, and the avatars of the message menu's reactions |
UserAvatar |
A user's image or initials, with an optional presence dot | Message authors, thread list items, mention suggestions, poll votes, and the member, add members, media and pinned message rows |
ChannelAvatar |
The channel's image, or its members' avatars | Channel list rows, through ChannelPreviewAvatar, the profile of channel details, the edit form, and the channel actions sheet |
AvatarGroup |
Up to four nodes arranged in a circle, and a count for the rest | Inside UserAvatarGroup |
UserAvatarGroup |
An AvatarGroup of users |
ChannelAvatar, for a channel without an image |
AvatarStack |
A row of overlapping nodes, and a count for the rest | Inside UserAvatarStack |
UserAvatarStack |
An AvatarStack of users |
The typing indicator, thread replies, thread list items and poll options |
The sizes are named. Each name is a diameter in points:
| Size | 2xl |
xl |
lg |
md |
sm |
xs |
|---|---|---|---|---|---|---|
| Width | 80 | 48 | 40 | 32 | 24 | 20 |
Avatar
Avatar renders imageUrl with the ImageComponent key of ComponentsContext. Without imageUrl, or once the image fails to load, it renders placeholder instead. After a load error it keeps the placeholder, even if imageUrl changes.
The avatar gets an accessibility label from accessibilityLabel, or, with SDK accessibility on, from name through the avatar.accessibilityLabel key, "Avatar of Cleo". A labeled avatar has the image role. Without a label, screen readers skip it.
| Prop | Type | Default | Description |
|---|---|---|---|
size |
'2xl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs' |
required | The diameter, from the table above. |
accessibilityLabel |
string |
The label screen readers announce. Replaces the one built from name. |
|
backgroundColor |
ColorValue |
semantics.avatarPaletteBg1 |
The color behind the image or the placeholder. |
imageUrl |
string |
The image to show. | |
name |
string |
The user's or channel's name, for the accessibility label. | |
placeholder |
React.ReactNode |
What shows without an image, such as initials or an icon. | |
showBorder |
boolean |
Draws a 1-point border in semantics.borderCoreOpacitySubtle. |
|
style |
StyleProp<ViewStyle> |
Applied to the circle, after the theme. |
UserAvatar
UserAvatar shows user.image. Without one, it shows the initials of user.name, one letter at xs and sm and two at the larger sizes, or a people icon when the user has no name. The background and text colors come from the five avatarPalette colors of the theme, picked by a hash of the user's id, so a user keeps the same color everywhere. The accessibility label is built from user.name, or user.id without one.
With showOnlineIndicator, it adds an OnlineIndicator on the top right of the circle, sized to the avatar.
| Prop | Type | Default | Description |
|---|---|---|---|
user |
UserResponse |
required | The user. |
size |
AvatarProps['size'] |
required | The diameter. |
showBorder |
boolean |
!!user.image |
Draws the border of Avatar. |
showOnlineIndicator |
boolean |
Shows the presence dot. It's always the online color. | |
style |
StyleProp<ViewStyle> |
Passed to Avatar. |
ChannelAvatar
ChannelAvatar picks what to show from the channel's state:
- With an image in the channel's data,
custom.image, it shows the image on a background picked by a hash of thecid. - Otherwise, when more than one member besides the current user is loaded, it shows a
UserAvatarGroupof the loaded members. - Otherwise, it shows a
UserAvatarof the other member, or a people icon in a channel where you're alone.
It re-renders when the image, the members or the other member's presence changes. With SDK accessibility on, screen readers announce it once, as "Direct chat with Cleo" or as "Channel with 5 members". A channel counts as a group when it has a name or more than two members.
| Prop | Type | Default | Description |
|---|---|---|---|
channel |
Channel |
required | The channel. |
size |
'lg' | 'xl' | '2xl' |
'xl' |
The diameter. |
showBorder |
boolean |
true |
Draws the border, around the image or the single user avatar. |
showOnlineIndicator |
boolean |
whether the other member of a two-member channel is online | Shows the presence dot on the user avatar or the group. |
isPreview |
boolean |
false |
Shows previewUri in place of the channel's image. |
previewUri |
string | null |
null |
The image to show while isPreview is true. null shows the members' avatars, as when the channel has no image. |
The channel edit form uses isPreview to show a picked image, or none, before it's saved.
AvatarGroup and UserAvatarGroup
AvatarGroup places its items in a circle of the given size:
- one item, beside a placeholder with a people icon;
- two items, top left and bottom right;
- three items, one on top and two below;
- four items, in a grid;
- five or more, the first two on top and a
BadgeCountwith+and the rest below.
UserAvatarGroup renders an AvatarGroup of UserAvatars, each with a 2-point border in semantics.borderCoreInverse, and a presence dot on the top right of the group. The inner avatars are sm, md and xl for a group of lg, xl and 2xl.
| Prop | Type | Default | Description |
|---|---|---|---|
size |
'lg' | 'xl' | '2xl' |
required | The diameter of the group. |
items |
React.ReactNode[] |
required | The avatars, usually four or fewer. |
UserAvatarGroupProps:
| Prop | Type | Default | Description |
|---|---|---|---|
size |
'lg' | 'xl' | '2xl' |
required | The diameter of the group. |
users |
UserResponse[] |
required | The users. |
showOnlineIndicator |
boolean |
true |
Shows the presence dot. It's always the online color. |
AvatarStack and UserAvatarStack
AvatarStack lays out the first maxVisible items in a row, each shifted over the one before it by overlap, a fraction of the diameter. When there are more items, a BadgeCount with the number of the others follows the row.
UserAvatarStack renders an AvatarStack of UserAvatars, each with a 2-point border in semantics.borderCoreInverse.
| Prop | Type | Default | Description |
|---|---|---|---|
items |
React.ReactNode[] |
required | The avatars. |
avatarSize |
'md' | 'sm' | 'xs' |
'sm' |
The diameter of each item, used for the spacing and for the size of the count. |
maxVisible |
number |
3 |
How many items show before the count. |
overlap |
number |
0 |
From 0, side by side, toward 1, one on top of the other. |
UserAvatarStackProps:
| Prop | Type | Default | Description |
|---|---|---|---|
users |
UserResponse[] |
required | The users. |
avatarSize |
'md' | 'sm' | 'xs' |
'sm' |
The size of each UserAvatar. |
maxVisible |
number |
3 |
Passed to AvatarStack. |
overlap |
number |
0 |
Passed to AvatarStack. |
Theming
The theme styles the base avatar with avatar.container, avatar.image and avatar.border, and the bordered avatars of UserAvatarStack with avatarStack.userAvatarWrapper. The colors come from the avatarPalette semantic tokens. See Theme object.
Example
A channel list without presence dots, and a row of the people in a call:
import { Text, View } from "react-native";
import type { UserResponse } from "stream-chat";
import { ChannelAvatar, UserAvatarStack } from "stream-chat-react-native";
import type {
ChannelAvatarProps,
ComponentOverrides,
} from "stream-chat-react-native";
const ChannelPreviewAvatar = (props: ChannelAvatarProps) => (
<ChannelAvatar {...props} showOnlineIndicator={false} />
);
// Pass these to WithComponents around ChannelList.
export const avatarOverrides: ComponentOverrides = {
ChannelPreviewAvatar,
};
export const CallParticipants = ({ users }: { users: UserResponse[] }) => (
<View style={{ alignItems: "center", flexDirection: "row", gap: 8 }}>
<UserAvatarStack
avatarSize="md"
maxVisible={4}
overlap={0.3}
users={users}
/>
<Text>{users.length} in the call</Text>
</View>
);ChannelPreviewView renders ChannelPreviewAvatar with the channel and size="xl".
Related
- Badges:
OnlineIndicatorandBadgeCount, which the avatars render. - Channel and thread hooks:
useChannelImageanduseChannelName, which read whatChannelAvatarshows. - Channel preview hooks:
useChannelPreviewDisplayPresence, the default ofshowOnlineIndicator. - Overriding components:
WithComponentsand theImageComponentkey.