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

Overlays and bottom sheets

Some of the SDK's UI opens on top of the screen: the message menu on a long press, the image gallery, the attachment picker, the list of who reacted, the poll screens. Each opens in one of these ways:

Kind What opens this way Drawn by
The message overlay the message menu OverlayProvider, above your screens
The gallery overlay the image gallery OverlayProvider, above your screens
Bottom sheets who reacted, more reactions, commands, the gallery's grid, a channel's options, a member's actions, the channel image picker BottomSheetModal, in a native modal window
The attachment picker the photo grid and the picker's sources Channel and Thread, below the composer
Full-screen modals polls' results, options and comments, poll creation, channel details' member list, media, files, pinned messages, editing a native modal window

The two overlays need OverlayProvider above the screen. The rest need nothing more than the Channel, Thread or ChannelDetails they belong to.

OverlayProvider

OverlayProvider goes around your navigation, above Chat, as in the Quick start. It renders your app, then on top of it a layer for the message menu and, while it's open, the image gallery. Its layer covers the whole window, so it draws above your navigation's headers and tab bars.

Prop What it does
value.style the theme of the overlays and everything else below OverlayProvider. See Theming
i18nInstance the Streami18n instance for the overlays' text. Pass the one you give Chat
accessibility the opt-in accessibility layer. See Accessibility
autoPlayVideo whether a video in the gallery starts playing when it opens
giphyVersion which rendition of a Giphy the gallery shows
numberOfImageGalleryGridColumns the number of columns of the gallery's grid

OverlayProvider draws in the window it's mounted in. A screen in another native window, such as a React Native Modal or a native modal presentation on iOS, needs an OverlayProvider of its own inside it, or the message menu opens behind the modal. See Chat in modals.

The message menu

A long press on a message opens its menu. A press on a message that failed to send opens it too, so the user can retry or delete it.

  1. The keyboard closes. On a long press, the device gives a haptic tap.
  2. The SDK measures where the message is on screen, and the overlay dims the screen behind it.
  3. The message itself moves into the overlay, in place.
  4. The reaction picker shows above the message, and the action list below it.

The menu doesn't open for a blocked message, for a message whose attachment has actions of its own, such as a Giphy preview the user is still choosing, or when onLongPressMessage on Channel replaces the long press. A long press on a message the server bounced asks the user to send it anyway, edit it or delete it instead.

The menu closes when the user picks an action or a reaction, taps the dimmed background, presses the Android back button, or rotates the device. When the message and the menu are taller than the screen, the user scrolls them by dragging.

What's in the menu:

Part Override key Shown when
The reaction picker, with a button for more emoji MessageReactionPicker the user has send-reaction in the channel
The action list MessageActionList, with MessageActionListItem for each item there are actions for the message
The dimmed background MessageOverlayBackground always

The actions in the list, and how to change them, are on Actions. The picker's reactions are the isMain entries of supportedReactions on Channel; the more-emoji button opens a bottom sheet with the SDK's full emoji set, whatever supportedReactions holds. See Reactions.

MessageOverlayBackground is read by OverlayProvider, so set it in a WithComponents around OverlayProvider. The picker and the action list render inside the message, so they take the overrides that reach the message.

The optional MessageActions key replaces the layout of the whole overlay. It receives the animated styles the default layout positions its parts with, hostStyle, topItemStyle, bottomItemStyle and portalHostStyle, and renders the portal hosts that the message, the picker and the action list move into. It's for a menu with a different arrangement; to change what's in the menu, override the parts above.

Fixed UI above a closing menu

When the menu closes, the message animates back into the list. A part of the screen that should stay drawn above it, such as a header inside the screen, goes in a PortalWhileClosingView: while the menu closes, it moves its children into the overlay above the message, and keeps their space in the layout. The SDK wraps the composer and the suggestion list this way. The Channel UI page shows it around a header.

Pressing an image or a video in a message opens the gallery on that item, with the message's other images and videos to swipe through.

Part Override key
The header: the back button, the sender and the time ImageGalleryHeader
The footer: the share button, the position, the grid button ImageGalleryFooter
The video controls in the footer ImageGalleryVideoControls
The grid of every item, in a bottom sheet ImageGalleryGrid

A tap hides and shows the header and footer. Pinching or a double tap zooms, and a swipe down closes the gallery, as do the back button in the header and the Android back button. The share button shows only when the share and file-system handlers are registered, which depends on the optional packages your app installs: see Installation.

The gallery is rendered by OverlayProvider, so these keys, and the icons the gallery uses, take effect only from a WithComponents around OverlayProvider. Its time format is the timestamp.ImageGalleryHeader translation key: see Localization.

Bottom sheets

The SDK's bottom sheets are BottomSheetModals. Each one is a React Native Modal, its own native window, so it opens above everything, the overlays and your navigation included, and needs no provider:

Sheet Opens from Content key
Who reacted a press on a message's reactions MessageUserReactions, with MessageUserReactionsItem and MessageUserReactionsAvatar
More reactions the more-emoji button of the reaction picker none
Commands the commands button of the attachment picker none
The gallery's grid the grid button of the gallery ImageGalleryGrid
A channel's options the options button of a channel-list row's swipe actions ChannelDetailsBottomSheet, with ChannelDetailsHeader
A member's actions a member in channel details ChannelMemberActionsSheet
The channel image editing the channel in channel details ChannelEditImageSheet

A sheet closes when the user drags it down, taps the backdrop, or presses the Android back button. A sheet shorter than the screen can be dragged up to full height. On iOS, the sheet moves up above the keyboard while it's open.

BottomSheetModal is exported, so your own sheets can match the SDK's:

import { useState } from "react";
import { Pressable, StyleSheet, Text, View } from "react-native";
import { BottomSheetModal } from "stream-chat-react-native";

export const ChannelRulesButton = ({ rules }: { rules: string }) => {
  const [visible, setVisible] = useState(false);

  return (
    <>
      <Pressable accessibilityRole="button" onPress={() => setVisible(true)}>
        <Text>Rules</Text>
      </Pressable>
      <BottomSheetModal
        enableDynamicSizing
        onClose={() => setVisible(false)}
        visible={visible}
      >
        <View style={styles.content}>
          <Text>{rules}</Text>
        </View>
      </BottomSheetModal>
    </>
  );
};

const styles = StyleSheet.create({
  content: { padding: 16 },
});
Prop Default What it does
visible whether the sheet is open. While it's false, nothing renders
onClose called when the user closes the sheet. Set visible to false in it
height half the window the sheet's height, capped to the window
enableDynamicSizing false sizes the sheet to its content, up to height
lazy false renders the content after the opening animation

It reads the theme, so render it below OverlayProvider or Chat. Its look is the theme's bottomSheetModal key: container, contentContainer, handle, overlay and wrapper.

The attachment picker

The attachment picker is a bottom sheet that Channel and Thread render below their children. The composer's attach button opens it. Unlike the sheets above, it isn't a separate window: it slides up inside the channel's screen, under the composer, and the screen's content stays above it. Opening the keyboard closes it, and so does the Android back button.

Its parts are AttachmentPickerSelectionBar, the row of sources, AttachmentPickerContent, what the selected source shows, and ImageOverlaySelectedComponent, the mark on a selected photo. Its sources and props are on Message composer UI.

Full-screen modals

The poll screens and the screens channel details opens are React Native Modals too. On iOS, most are presented as a page sheet, and the media, files and pinned messages screens of channel details as full screen; on Android, all are full screen. They close on the Android back button.

Screen Content key
A poll's results PollResultsContent, and PollOptionFullResultsContent for one option
A poll's options PollAllOptionsContent
A poll's comments PollAnswersListContent
Creating a poll CreatePollContent, which has no default and replaces the built-in form
Channel details' member list ChannelMemberList
Channel details' media, files and pinned messages MediaList, FileAttachmentList, PinnedMessageList
Editing a channel, adding members ChannelEditDetailsForm, ChannelAddMembersForm

A dialog that only asks for text, such as suggesting a poll option or adding a comment, is a small Modal of its own. Confirmations, such as deleting a message or leaving a channel, use the platform's Alert.

Back button handling

On Android, the back button closes what's on top before your navigation sees it:

Open The back button
the message menu closes it
the image gallery closes it
a bottom sheet or a full-screen modal closes it, through the Modal's onRequestClose
the attachment picker, with a source selected closes it
nothing goes to your navigation

The overlays and the picker register their BackHandler listeners while they're mounted and return true only while they have something open, so your own listeners keep working the rest of the time.

Pitfalls

  • OverlayProvider inside a screen. Its overlays then cover only that screen, under the navigation's header. Put it around the navigation container's content, once.
  • A chat screen in a native modal. The message menu opens in the window behind it. Give the modal its own OverlayProvider.
  • Gallery or overlay overrides below OverlayProvider. OverlayProvider never sees them. Put that WithComponents above it.
  • A header that the closing message animates over. Wrap it in PortalWhileClosingView.
  • Expecting the attachment picker over the whole screen. It belongs to the Channel's screen and opens under the composer, not in its own window.

Used in: Message actions, Reactions, Attachments and uploads and Chat in modals.