Info:
This is release candidate documentation for Stream Chat React Native SDK v10. For the latest stable version, see the latest version (v9).

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 UserAvatar for a user and ChannelAvatar for a channel. They pick the image, the initials, the background color and the accessibility label. Avatar is the base they share, for content of your own.
  • Every avatar reads the theme, which OverlayProvider and Chat provide. ChannelAvatar also reads the chat client, so render it inside Chat.
  • 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 as MessageAuthor, MessageRepliesAvatars or MessageUserReactionsAvatar.
  • UserAvatar doesn't read user.online. Pass it as showOnlineIndicator, 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:

  1. With an image in the channel's data, custom.image, it shows the image on a background picked by a hash of the cid.
  2. Otherwise, when more than one member besides the current user is loaded, it shows a UserAvatarGroup of the loaded members.
  3. Otherwise, it shows a UserAvatar of 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 BadgeCount with + 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:

src/avatars.tsx
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".