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

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 EmptyList for a list that has nothing in it yet, and EmptySearchResult for a search that matched nothing. The pinned messages list of channel details uses them this way.
  • Pass EmptyList an icon component, not an element. It sets the icon's size and color.
  • SelectionCircle has no accessibility state of its own. Put accessibilityState={{ selected }} on the row it sits in, as the add members form does.
  • Every component here reads the theme, which OverlayProvider and Chat provide.

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:

src/ContactPicker.tsx
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>
        );
      }}
    />
  );
};