Repository navigation
馃敟[馃悰] Issues with chat overlays in modals聽#3860
Description
Issue
Assume we have everything configured in our app to show a chat:
Regular chat in our root view - so good so far
For various reasons, we might want to have a text chat inside a modal in some instances in our app. Assume react-navigation as presentation: 'fullScreenModal'. However, if we do this, the long-press overlay no longer works. The message becomes invisible and the overlay does not show:
I have long-pressed the "Test" message here, note there's no black overlay or reactions and the message itself is gone
The only partial fix I've found is to provide the modal its own <OverlayProvider />. This goes against the docs, but stay with me for a sec:
<Stack.Screen
name="ChatModal"
component={ChatModalScreen}
layout={({ children }) => (
// Give the modal its own overlay provider so the long-press can sit on top
<OverlayProvider>{children}</OverlayProvider>
)}
options={{
presentation: 'fullScreenModal',
title: 'Modal chat',
}}
/>This does allow the reactions to show in the modal view (with a couple of caveats):
We have our overlay inside the modal now (albeit with some issues with the header)
However, now if we close the modal, the overlays are now broken for our original chat: long-pressing a message shows an overlay with a misaligned reply overlay and no reaction bar:
Navigating back to our root view, the overlays no longer layer properly here
If you look closely, the reaction picker is actually behind the message actions
Steps to reproduce
Steps to reproduce the behavior:
- Run a simple app that includes a text chat in the root view and a
react-navigationfull screen modal that has a chat (example in customization below but can also provide a repro repo if it's useful). - Open the modal view
- long-press a message in the chat to open reactions/message actions in the modal view.
Expected behavior
Expect that with a single root <OverlayProvider /> that the long-press actions would still work when the chat is in a modal - or at least have a way to allow these to function in a modal.
Project Related Information
Customization
Click To Expand
Basic app
// Main app
<SafeAreaProvider>
<GestureHandlerRootView style={styles.container}>
<ChatWrapper>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Chat"
component={ChatScreen}
options={{ title: 'Chat' }}
/>
<Stack.Screen
name="ChatModal"
component={ChatModalScreen}
// Comment as necessary, this fixes one issue but causes another
// layout={({ children }) => (
// <OverlayProvider>{children}</OverlayProvider>
// )}
options={{
presentation: 'fullScreenModal',
title: 'Modal chat',
}}
/>
</Stack.Navigator>
</NavigationContainer>
</ChatWrapper>
<StatusBar style="auto" />
</GestureHandlerRootView>
</SafeAreaProvider>
// Chat Screen
<View style={styles.container}>
<Button title="Open modal" onPress={() => navigation.navigate('ChatModal')} />
<StreamTextChat channelId={mainChannelId} />
</View>
// ChatModalScreen
export function ChatModalScreen({ navigation }: ChatModalScreenProps) {
return (
<View style={styles.container}>
<Button title="Close" onPress={() => navigation.goBack()} />
<StreamTextChat channelId={modalChannelId} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});StreamTextChat is basically vanilla from the getting started tutorial i.e.:
<Channel
bottomInset={bottom}
channel={channel}
>
<MessageList />
<MessageComposer />
</Channel>Offline support
-
The feature I'm having does not occur when offline support is disabled. (stripe out if not applicable)
Environment
Click To Expand
package.json:
{
"name": "sandbox",
"version": "1.0.0",
"main": "index.ts",
"dependencies": {
"@react-native-community/netinfo": "12.0.1",
"@react-navigation/elements": "^2.9.44",
"@react-navigation/native": "^7.5.0",
"@react-navigation/native-stack": "^7.20.0",
"expo": "~57.0.28",
"expo-image-manipulator": "~57.0.21",
"expo-status-bar": "~57.0.1",
"react": "19.2.3",
"react-native": "0.86.3",
"react-native-gesture-handler": "~2.32.0",
"react-native-reanimated": "4.5.1",
"react-native-safe-area-context": "~5.7.0",
"react-native-screens": "~4.26.0",
"react-native-svg": "15.15.4",
"react-native-teleport": "^1.2.2",
"react-native-worklets": "0.10.1",
"stream-chat-expo": "^9.9.4"
},
"devDependencies": {
"@types/react": "~19.2.2",
"typescript": "~6.0.3"
},
"scripts": {
"start": "expo start",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web"
},
"private": true
}
}- Platform that you're experiencing the issue on:
- iOS
- Android
- iOS but have not tested behavior on Android
- Android but have not tested behavior on iOS
- Both
stream-chat-react-nativeversion you're using that has this issue:"stream-chat-expo": "^9.9.4"
- Device/Emulator info:
- iPhone 17 iOS 26.2
Additional context
Can provide a full reproduction repo if required. I haven't tried this with expo navigation, only react-navigation.
Screenshots
Click To Expand
See the main issue body
Activity
isekovanic commentedon Oct 15, 2026
Hi @zbarbuto ,
The problem is something relatively different here. Specifically, this blogpost is something you might want to read with regards to it.
Modals simply need to be self contained and carry their own
OverlayProvider(and conversely their own variety of higher order views that come with our main chat providers), similar to how they'd need to carry their ownGestureHandlerRootViewfor RNGH integration for example.The main problem with having 2
OverlayProviders is the fact that the state layer is shared (and so are the portal hosts that relate to them directly). This is kind of breaking to fix (in V9 at least) and there are also a bunch of other implications that are sort of hard to work around. However in these types of specific scenarios it should be relatively fine to use.I'll look into the bug you're having with the provider underneath though, that might be related to unmounting hosts or something. That's my current theory anyway.
I'll keep you posted if I'm able to reproduce it.
zbarbuto commentedon Oct 15, 2026
Thanks for the info and yeah, I thought it might be related to that as I've come across the issue before using Teleport and I know stream did recently start using teleport in a recent major version. It's sort of why I tried adding the
OverlayProviderto the modal to combat it. But yes I could see hints that it's probably not the right solution.Even if not allowing multiple
OverlayProviders, having some other export to wrap modals to support allowing chats in both regular stack pages and modals would be extremely useful.isekovanic commentedon Oct 15, 2026
Yep, I have a fix ready I'm just testing stuff out. I'll update the docs as well so that this part is covered well once that's done.
I'll keep you posted !
zbarbuto commentedon Oct 15, 2026
Legend! Thanks so much for getting to this so quickly.
fix: differentiate host layers by id and self register (#3862)
isekovanic commentedon Oct 16, 2026
Hi again @zbarbuto,
The fix is merged in #3862 and is available in
9.10.1-beta.1, so you can already test it by bumping the version.With it, multiple
OverlayProviders can be mounted at the same time, so the root chat keeps working after the modal closes. You don't need any special export for this, a regularOverlayProviderinside the modal is enough.One thing to change on your end though, instead of wrapping the screen through
layout, wrap the modal's own navigator, the same way the rootOverlayProviderwraps your main stack. Withlayoutthe native header still sits above the provider, so the overlay can't cover it and ends up offset by the header's height (that was the header thingy you mentioned). So something like:A couple of things to keep in mind:
OverlayProviderthe same props as your root one (theme,i18nInstance,accessibility), otherwise everything inside the modal falls back to the defaultsfullScreenModalworks best. Sheet presentations likepageSheetandformSheetdon't start at the top of the screen, so the overlay will be slightly offset thereOverlayProviderat the root plus one per modal. Having them side by side (for example one per tab) isn't supportedI'm also adding a guide on this to the docs. Let me know how the beta works out for you ! Once I'm done with the docs I'll follow up here again once this has been released.
isekovanic commentedon Oct 19, 2026
This has now been released here as well !
Here is the cookbook I promised as well, in case someone finds it useful: https://getstream.io/chat/docs/sdk/react-native/guides/chat-in-modals/
zbarbuto commentedon Oct 22, 2026
Can confirm this new release has fixed my issues 馃憤