Skip to main content

Platform notes

Android

Keyboard configuration

If you are using Create React Native App / Expo, no Android specific installation steps are required. Otherwise, we recommend modifying your project configuration:

Make sure you have android:windowSoftInputMode="adjustResize" in your AndroidManifest.xml:

<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">

For Expo, you can append KeyboardAvoidingView after Chat (Android only):

<View style={{ flex: 1 }}>
<Chat />
{Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />}
</View>

Web (react-native-web)

Install the web renderer alongside the library:

yarn add react-native-web react-dom
Expo / Metro (recommended) - no extra config
npx expo start --web

Nothing else to set up. Metro runs Babel over node_modules, so this package's JSX and its Reanimated worklets get transpiled the same way your own code does. The example app runs on web exactly like this.

Other bundlers (webpack, Vite, Next.js) - the package must be transpiled

The published files are ES modules with JSX left in place, and the component uses Reanimated worklets, which need react-native-reanimated/plugin to run. Bundlers that skip node_modules when transpiling - webpack's babel-loader does by default - will choke on that. So outside Metro you need to:

  1. Alias react-native to react-native-web and let the resolver pick up .web.js / .web.tsx extensions
  2. Run @kesha-antonov/react-native-chat - and the React Native packages it depends on - through Babel with @react-native/babel-preset and react-native-reanimated/plugin, instead of excluding all of node_modules

In Next.js that is transpilePackages in next.config.js; in a plain webpack setup it means widening the babel-loader rule's exclude so these packages are included.

React Strict DOM

Works inside an RSD tree - verified on iOS and Expo web

Chat drops into a React Strict DOM app unchanged. RSD's native build renders through React Native, so <Chat> is just another RN subtree:

import { css, html } from 'react-strict-dom'
import { Chat } from '@kesha-antonov/react-native-chat'

const styles = css.create({
root: { display: 'flex', flexDirection: 'column', height: '100%' },
})

<html.div data-layoutconformance='strict' style={styles.root}>
<Chat messages={messages} onSend={onSend} user={user} />
</html.div>

Three things to know:

  • Web needs react-native-web. RSD's web build contains no React Native code at all, so Chat does not resolve there on its own. Expo web gives you react-native-web already, so RSD (real DOM) and Chat (RNW's DOM output) render side by side in one tree. A Vite or Next.js RSD app has to add the alias and transpile step from the section above
  • Metro needs unstable_enablePackageExports: true. RSD publishes only an exports map with no main, so with package exports off it fails to resolve. This is the default on recent Expo SDKs
  • StyleX styles do not reach Chat. It takes React Native style objects and its own theme prop, not css.create output. On native, compat.native is the bridge if you want RSD to drive a wrapper around it