Lists and indicators
These components fill the states and marks of lists. They draw what an empty list or an empty search shows, the selection mark of a row, the play mark on a video, and the spinner. Every component on this page is exported from stream-chat-react-native and stream-chat-expo, and none has an override key. The loading, error and empty states of the channel and message lists are separate components, on Indicators.
Best practices
- Use
EmptyListfor a list that has nothing in it yet, andEmptySearchResultfor a search that matched nothing. The pinned messages list of channel details uses them this way. - Pass
EmptyListan icon component, not an element. It sets the icon's size and color. SelectionCirclehas no accessibility state of its own. PutaccessibilityState={{ selected }}on the row it sits in, as the add members form does.- Every component here reads the theme, which
OverlayProviderandChatprovide.
Available components
| Component | What it shows | Where the SDK renders it |
|---|---|---|
EmptyList |
An icon, a title and a subtitle, centered | The empty media, files and pinned messages lists of channel details |
EmptySearchResult |
A search icon and a line of text, centered | The member list and the add members form when they're empty, and the pinned messages list when a search matches nothing |
SelectionCircle |
An empty circle, or a filled one with a check mark | The rows of the add members form |
VideoPlayIndicator |
A play icon in a circle | Video thumbnails in messages, quoted replies and link previews, and the image gallery's grid |
Spinner |
A rotating loading icon | LoadingIndicator, the channel list's next page, and a loading video in the image gallery |
EmptyList
EmptyList fills its container and centers the icon, at 32 points in semantics.textTertiary, above the title and the subtitle.
| Prop | Type | Default | Description |
|---|---|---|---|
icon |
React.ComponentType<IconProps> |
required | The icon component to render. |
title |
string |
required | The main line. |
subtitle |
string |
A line under the title. |
The theme styles it with emptyList.container, emptyList.title and emptyList.subtitle.
EmptySearchResult
EmptySearchResult fills its container and centers the Search icon of ComponentsContext above label.
| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
required | The text to show. |
The theme styles it with emptySearchResult.container and emptySearchResult.text.
SelectionCircle
SelectionCircle is a 24-point circle. Unselected, it has a border in semantics.borderCoreDefault. Selected, it's filled with semantics.accentPrimary and shows the Checkmark icon.
| Prop | Type | Default | Description |
|---|---|---|---|
selected |
boolean |
required | Which of the two to show. |
The theme styles it with selectionCircle.circle and selectionCircle.circleSelected.
VideoPlayIndicator
VideoPlayIndicator draws the Play icon of ComponentsContext on semantics.controlPlayButtonBg. It's only a mark and isn't pressable. Put it over a thumbnail and handle the press on the thumbnail.
| Prop | Type | Default | Description |
|---|---|---|---|
size |
'sm' | 'md' | 'lg' |
required | A circle of 20, 40 or 48 points, with an icon of 10, 16 or 20 points. |
Spinner
Spinner turns the Loading icon of ComponentsContext once every 800 milliseconds, colored with semantics.accentPrimary. Replacing the Loading icon changes every Spinner. A few screens, such as the next page of the channel details lists, show React Native's ActivityIndicator instead.
| Prop | Type | Default | Description |
|---|---|---|---|
height |
number |
The height of the spinner and of its icon. | |
width |
number |
The width of the spinner and of its icon. | |
style |
StyleProp<ViewStyle> |
Applied to the rotating view first, so the default style, the theme, height and width override it. |
Pass height and width, which also set the size of the spinner's view. LoadingIndicator passes 20 for both. The theme styles it with spinner.
Example
A list of your own with an empty state, a search state and selectable rows:
import { FlatList, Pressable, Text } from "react-native";
import {
EmptyList,
EmptySearchResult,
SelectionCircle,
useComponentsContext,
} from "stream-chat-react-native";
type Contact = { id: string; name: string };
export const ContactPicker = ({
contacts,
onToggle,
query,
selectedIds,
}: {
contacts: Contact[];
onToggle: (id: string) => void;
query: string;
selectedIds: Set<string>;
}) => {
const { icons } = useComponentsContext();
return (
<FlatList
data={contacts}
keyExtractor={(contact) => contact.id}
ListEmptyComponent={
query ? (
<EmptySearchResult label={`No contacts match "${query}"`} />
) : (
<EmptyList
icon={icons.UserAdd}
subtitle="Invite people to see them here"
title="No contacts yet"
/>
)
}
renderItem={({ item }) => {
const selected = selectedIds.has(item.id);
return (
<Pressable
accessibilityRole="button"
accessibilityState={{ selected }}
onPress={() => onToggle(item.id)}
style={{
alignItems: "center",
flexDirection: "row",
gap: 12,
padding: 12,
}}
>
<Text style={{ flex: 1 }}>{item.name}</Text>
<SelectionCircle selected={selected} />
</Pressable>
);
}}
/>
);
};Related
- Indicators: the loading, error and empty states of the lists, and the network indicator.
- Channel details lists: the lists that render these components.
- Overriding components: replacing the
Loading,Play,SearchandCheckmarkicons. - Theme object: the
emptyList,emptySearchResult,selectionCircleandspinnerkeys.