Badges
Badges are the small marks the SDK puts on top of or next to other UI: unread counts, the "+3" of an avatar group, presence dots, the mark of a failed message, and the label of a GIF provider. Every component on this page is exported from stream-chat-react-native and stream-chat-expo, and none has an override key: the SDK renders them directly, so you replace a badge by replacing the component around it.
Best practices
- Use
BadgeNotificationfor a count that needs attention, such as unread messages, andBadgeCountfor a neutral count, such as how many more avatars there are. - Give
BadgeNotificationanaccessibilityLabelthat says what the number counts. Without one, a screen reader reads the bare number. - Pass
OnlineIndicatorthe presence you read, such asuser.online. It doesn't read presence itself. - Every badge reads the theme, which
OverlayProviderandChatprovide.
Available components
| Component | What it shows | Where the SDK renders it |
|---|---|---|
BadgeCount |
A count in a neutral pill | AvatarGroup and AvatarStack, for the items left out |
BadgeNotification |
A count in a colored pill with a border | The unread count of channel list rows, thread list items and the scroll-to-bottom button, and the order of selected media in the attachment picker |
OnlineIndicator |
A presence dot | UserAvatar and UserAvatarGroup |
ErrorBadge |
An exclamation mark in a circle of the error color | A failed message, and the latest message of a channel list row when it failed to send |
GiphyBadge |
The Giphy logo and "GIPHY" | Giphy attachments |
ImgurBadge |
The Imgur logo and "IMGUR" | Nowhere. Render it yourself. |
BadgeCount
BadgeCount renders count as it is, so pass "+3" for a plus sign. The pill is at least as wide as it's tall: 20, 24, 32 or 40 points for sm, md, lg and xl. It's drawn with semantics.badgeBgDefault, semantics.badgeText and a border in semantics.borderCoreSubtle.
| Prop | Type | Default | Description |
|---|---|---|---|
count |
string | number |
required | What the badge says. |
size |
'sm' | 'md' | 'lg' | 'xl' |
required | The height. |
BadgeNotification
BadgeNotification renders count on semantics.badgeBgPrimary, badgeBgError or badgeBgNeutral, inside a 2-point border in semantics.badgeBorder that separates it from what it sits on. sm is 20 points tall and xs 16.
| Prop | Type | Default | Description |
|---|---|---|---|
count |
number |
required | The number. |
size |
'sm' | 'xs' |
required | The height. |
type |
'primary' | 'error' | 'neutral' |
'primary' |
The background color. |
accessibilityLabel |
string |
Announced in place of the number, such as "3 unread messages". | |
testID |
string |
Set on the text. |
It shows count as it is, so cap large numbers yourself, for example at 99.
OnlineIndicator
OnlineIndicator is a dot in semantics.presenceBgOnline or semantics.presenceBgOffline, with a border in semantics.presenceBorder. The avatars place it on their edge and pick the size to match.
| Prop | Type | Default | Description |
|---|---|---|---|
online |
boolean |
required | Picks the online or the offline color. |
size |
'xl' | 'lg' | 'sm' | 'md' |
required | 16, 14, 12 or 8 points for xl, lg, md and sm, with a 1-point border at sm and 2 points otherwise. |
ErrorBadge
ErrorBadge draws the Exclamation icon of ComponentsContext in a circle of semantics.badgeBgError. ErrorBadgeProps are the props of a React Native View, which go to the circle, plus:
| Prop | Type | Default | Description |
|---|---|---|---|
size |
'xs' | 'sm' | 'md' |
required | 16, 20 or 24 points. |
style |
StyleProp<ViewStyle> |
Applied to the circle after the default style. |
GiphyBadge and ImgurBadge
GiphyBadge and ImgurBadge take no props. Each draws the provider's icon from ComponentsContext, Giphy or Imgur, and its name, on semantics.badgeBgOverlay. The Giphy attachment shows GiphyBadge on the image.
Example
A tab label with an unread count, and a status line with a presence dot:
import { Text, View } from "react-native";
import { BadgeNotification, OnlineIndicator } from "stream-chat-react-native";
export const ChatsTabLabel = ({ unreadCount }: { unreadCount: number }) => (
<View style={{ alignItems: "center", flexDirection: "row", gap: 6 }}>
<Text>Chats</Text>
{unreadCount > 0 ? (
<BadgeNotification
accessibilityLabel={`${unreadCount} unread`}
count={Math.min(unreadCount, 99)}
size="sm"
/>
) : null}
</View>
);
export const PresenceLine = ({ online }: { online: boolean }) => (
<View style={{ alignItems: "center", flexDirection: "row", gap: 6 }}>
<OnlineIndicator online={online} size="sm" />
<Text>{online ? "Online" : "Offline"}</Text>
</View>
);Related
- Avatars: the avatars that render
OnlineIndicatorandBadgeCount. - Read state and unread counts: where unread counts come from.
- Theme object: the semantic tokens the badges are drawn with.