Skip to main content

Props reference

Every group below is collapsed - open the one you need.

Core configuration, refs & theming

Core Configuration

  • messages (Array) - Messages to display
  • user (Object) - User sending the messages: { _id, name, avatar }
  • onSend (Function) - Callback when sending a message
  • messageIdGenerator (Function) - Generate an id for new messages. Defaults to a simple random string generator.
  • locale (String) - Locale to localize the dates. You need first to import the locale you need (ie. require('dayjs/locale/de') or import 'dayjs/locale/fr')
  • colorScheme ('light' | 'dark') - Force color scheme (light/dark mode). When set to 'light' or 'dark', it overrides the system color scheme. When undefined, it uses the system color scheme. Default is undefined.
  • theme (Object) - Override the default light theme tokens (colors / radii / spacing / typography / avatar / sendButton / composer / voice). Deep-merged over defaultLightTheme; any subset is allowed. See Theming & Dark Mode.
  • darkTheme (Object) - Same as theme, applied when the resolved color scheme is dark (deep-merged over defaultDarkTheme).
  • icons (Object) - Icon override registry. Supply a render function for any built-in icon to replace it (e.g. with lucide-react-native). See Custom icons.
  • labels (Object) - Override any UI string. See Localization (i18n).

Refs

  • messagesContainerRef (FlatList ref) - Ref to the flatlist
  • textInputRef (TextInput ref) - Ref to the text input
Keyboard & layout

Keyboard & Layout

  • keyboardProviderProps (Object) - Props to be passed to the KeyboardProvider for keyboard handling. No defaults are applied - in particular Chat does not set statusBarTranslucent / navigationBarTranslucent, because on Android those change the activity window and the change outlives the chat screen (#2755). react-native-keyboard-controller turns them on by itself when the app is genuinely edge-to-edge, so there is nothing to set in a normal app.

    Only used when Chat mounts the provider itself. If your app already mounts a KeyboardProvider (the setup react-native-keyboard-controller recommends - once, at the root), Chat detects it and reuses it instead of nesting a second one, and this prop is ignored. Configure the provider where you mount it.

  • enableKeyboardProvider (Bool) - Render the built-in KeyboardProvider; default is true. You do not need to turn this off just because your app mounts its own provider - that case is detected and reused. Set it to false only to opt out completely, e.g. when the provider's edge-to-edge behavior causes layout shift or a header jump on Android/Expo.

  • enableGestureHandlerRootView (Bool) - Render the GestureHandlerRootView Chat mounts around itself; default is true. Unlike KeyboardProvider, an existing one can't be auto-detected - react-native-gesture-handler doesn't expose that publicly - so set this to false yourself if your app (or a library it uses, e.g. a bottom sheet) already mounts one at the root. Nesting a second one changes the native view hierarchy around the composer, which has been observed to make a rare Fabric/Yoga layout assertion on iOS more likely, especially when Chat is mounted and unmounted while the keyboard is open (#17).

  • keyboardAvoidingViewProps (Object) - Props to be passed to the KeyboardAvoidingView. See keyboardVerticalOffset below for proper keyboard handling.

  • isAlignedTop (boolean | 'auto') - Where the bubbles sit while the whole conversation fits on screen; once it is taller than the list this has no effect. false (default) keeps the usual bottom-anchored chat, true pins the messages to the top, and 'auto' pins them to the top while the keyboard is closed and re-anchors them to the bottom while it is open - so a short conversation starts under the header and moves above the keyboard when the composer is focused (#2736). Works with either isInverted setting; ignored when isFlashListEnabled is set, since FlashList positions its own items.

  • isInverted (Bool) - Reverses display order of messages; default is true

Understanding keyboardVerticalOffset

keyboardVerticalOffset tells the KeyboardAvoidingView how far down the screen its container starts. That distance depends on the navigation header and on anything else you render above the chat.

You do not normally need to set it. Chat measures its own position on screen and uses that, so the input toolbar sits on the keyboard whether the chat is full-screen or under a navigation header. The measurement comes from the SafeAreaProvider frame and updates on rotation and layout changes.

Pass your own value only to add extra space above the keyboard - it replaces the measured one:

<Chat keyboardAvoidingViewProps={{ keyboardVerticalOffset: headerHeight + 16 }} />

If you do, sanity-check it on device: a toolbar behind the keyboard means the value is too small, a gap above the keyboard means it is too large. useHeaderHeight() is the usual source, but some navigator setups report a value that does not match the header you actually render.

Upgrading from 4.1.0 or earlier: the default used to be insets.top, which could not account for a navigation header - so most apps passed useHeaderHeight() to compensate. That is no longer needed; drop it and let Chat measure, or the toolbar will float above the keyboard by the header height.

Text input, composer & actions

Text Input & Composer

  • text (String) - Input text; default is undefined, but if specified, it will override Chat's internal state. Useful for managing text state outside of Chat (e.g. with Redux). Don't forget to implement textInputProps.onChangeText to update the text state.
  • initialText (String) - Initial text to display in the input field
  • isSendButtonAlwaysVisible (Bool) - Always show send button in input text composer; default false, show only when text input is not empty
  • isTextOptional (Bool) - Allow sending messages without text (useful for media-only messages); default false. Use with isSendButtonAlwaysVisible for media attachments.
  • isMultiline (Bool) - Whether the composer accepts multiple lines; default true. With true the return key inserts a newline and you send with the send button. Set false for a single-line composer whose return key sends the message (the keyboard's return key becomes "send" and stays open afterwards).
  • renderInputToolbar (Component | Function) - Custom message composer container
  • renderComposer (Component | Function) - Custom text input message composer
  • renderSend (Component | Function) - Custom send button; you can pass children to the original Send component quite easily, for example, to use a custom icon (example)
  • renderActions (Component | Function) - Custom action button on the left of the message composer
  • renderAccessory (Component | Function) - Custom second line of actions below the message composer
  • onPressEmoji (Function) - Callback for the optional emoji button on the left of the composer field. When omitted, the emoji button is hidden.
  • audioRecording (Object) - Enable Telegram-style hold-to-record voice notes. { isEnabled, minDurationMs?, onError? }. Requires the optional expo-audio peer (and react-native-audio-api for the playback waveform); the mic button is hidden when it is absent.
  • videoRecording (Object) - Enable record-and-send video messages. { isEnabled, maxDuration?, onError? }. Uses react-native-vision-camera for round camera notes, falling back to expo-image-picker's system camera.
  • textInputProps (Object) - props to be passed to the <TextInput>.

Composer height - there are no height props. The composer starts one line tall and grows with its content. Constrain it through textInputProps.style (e.g. { maxHeight: 120 }), which is applied after the measured height and wins.

Actions & Action Sheet

  • actions (Array) - Action options for the composer "+" button. Array of { title, action }; add icon (and optional color) to an action to render a Telegram-style attachment grid (tiles) instead of a list. Opens the built-in themed AttachmentSheet - no extra dependency.
  • onPressActionButton (Function) - Callback when the "+" button is pressed (if set, the built-in AttachmentSheet is not shown)
  • actionSheet (Function) - Escape hatch for a custom system action sheet. The bundled @expo/react-native-action-sheet dependency was removed, so context.actionSheet() defaults to a no-op; pass your own implementation (with ActionSheetProvider in your tree) if you relied on it.
  • actionSheetOptionTintColor (String) - Tint color for action labels in the attachment sheet
Messages, container & bubbles

Messages & Message Container

  • messagesContainerStyle (Object) - Custom style for the messages container
  • renderMessage (Component | Function) - Custom message container
  • renderLoading (Component | Function) - Render a loading view when initializing
  • renderChatEmpty (Component | Function) - Custom component to render in the ListView when messages are empty
  • renderChatFooter (Component | Function) - Custom component to render below the MessagesContainer (separate from the ListView)
  • listProps (Object) - Extra props to be passed to the messages <FlatList>. Supports all FlatList props including maintainVisibleContentPosition for keeping scroll position when new messages arrive (useful for AI chatbots).
  • isFlashListEnabled (Bool) - Render messages with @shopify/flash-list v2 instead of FlatList; default is false. See FlashList.

Message Bubbles & Content

  • renderBubble (Component | Function(props: BubbleProps)) - Custom message bubble. Receives BubbleProps as parameter.
  • renderMessageText (Component | Function) - Custom message text
  • renderMessageImage (Component | Function) - Custom message image
  • renderMessageVideo (Component | Function) - Custom message video
  • renderMessageAudio (Component | Function) - Custom message audio
  • renderMessageLocation (Component | Function) - Custom renderer for IMessage.location; defaults to a map card that opens the system maps app on tap
  • messageActions (Array | Function(message)) - Telegram-style long-press context menu. Each item is { label, icon?, onPress, destructive? }. See Message actions.
  • renderCustomView (Component | Function) - Custom view inside the bubble
  • isCustomViewBottom (Bool) - Determine whether renderCustomView is displayed before or after the text, image and video views; default is false
  • onPressMessage (Function(context, message)) - Callback when a message bubble is pressed
  • onLongPressMessage (Function(context, message)) - Callback when a message bubble is long-pressed; you can use this to show action sheets (e.g., copy, delete, reply)
  • isMessageGestureEnabled (Bool | Function(message)) - Whether the bubble itself is part of the row's tap / long-press surface that reactions and messageActions rely on; default is true. Pass false, or a predicate, for messages that render natively interactive content - the row beside the bubble stays pressable either way. See Interactive content inside bubbles.
  • imageProps (Object) - Extra props to be passed to the <Image> component created by the default renderMessageImage
  • imageStyle (Object) - Custom style for message images
  • videoProps (Object) - Extra props to be passed to the video component created by the required renderMessageVideo
  • messageTextProps (Object) - Extra props to be passed to the MessageText component. Useful for customizing link parsing behavior, text styles, and matchers:
    • matchers - Custom matchers for linking message content (like URLs, phone numbers, hashtags, mentions)
    • linkStyle - Custom style for links
    • email / phone / url - Enable/disable parsing (default: true)
    • hashtag / mention - Enable/disable parsing (default: false)
    • hashtagUrl / mentionUrl - Base URLs (e.g. 'https://x.com/hashtag')
    • stripPrefix - Strip 'http://' or 'https://' from URL display (default: false)
    • TextComponent - Custom Text component to use (e.g., from react-native-gesture-handler)

A custom matcher, replacing the default phone linking with an action sheet:

<Chat
messageTextProps={{
phone: false, // Disable default phone number linking
matchers: [
{
type: 'phone',
pattern: /\+?[1-9][0-9\-\(\) ]{7,}[0-9]/g,
getLinkUrl: (replacerArgs: ReplacerArgs): string => {
return replacerArgs[0].replace(/[\-\(\) ]/g, '')
},
getLinkText: (replacerArgs: ReplacerArgs): string => {
return replacerArgs[0]
},
style: styles.linkStyle,
onPress: (match: CustomMatch) => {
const url = match.getAnchorHref()

const options: {
title: string
action?: () => void
}[] = [
{ title: 'Copy', action: () => setStringAsync(url) },
{ title: 'Call', action: () => Linking.openURL(`tel:${url}`) },
{ title: 'Send SMS', action: () => Linking.openURL(`sms:${url}`) },
{ title: 'Cancel' },
]

showActionSheetWithOptions({
options: options.map(o => o.title),
cancelButtonIndex: options.length - 1,
}, (buttonIndex?: number) => {
if (buttonIndex === undefined)
return

const option = options[buttonIndex]
option.action?.()
})
},
},
],
linkStyle: { left: { color: 'blue' }, right: { color: 'lightblue' } },
}}
/>

See the full example in LinksExample.

Avatars, username, date & time, system messages

Avatars

  • renderAvatar (Component | Function) - Custom message avatar; set to null to not render any avatar for the message
  • isUserAvatarVisible (Bool) - Whether to render an avatar for the current user; default is false, only show avatars for other users
  • isAvatarVisibleForEveryMessage (Bool) - When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is false
  • onPressAvatar (Function(user)) - Callback when a message avatar is tapped
  • onLongPressAvatar (Function(user)) - Callback when a message avatar is long-pressed
  • isAvatarOnTop (Bool) - Render the message avatar at the top of consecutive messages, rather than the bottom; default is false

Username

  • isUsernameVisible (Bool) - Indicate whether to show the user's username inside the message bubble; default is false
  • renderUsername (Component | Function) - Custom Username container

Date & Time

  • timeFormat (String) - Format to use for rendering times; default is 'LT' (see Day.js Format)

  • dateFormat (String) - Format to use for rendering dates; default is 'D MMMM' (see Day.js Format)

  • dateFormatCalendar (Object) - Format to use for rendering relative times; default is { sameDay: '[Today]' } (see Day.js Calendar)

  • renderDay (Component | Function) - Custom day above a message. This is also how the day label is styled - it receives DayProps (createdAt, dateFormat, dateFormatCalendar, containerStyle, wrapperStyle, textProps, isAnimated), so render the built-in Day with the styles you want:

    import { Chat, Day, DayProps } from '@kesha-antonov/react-native-chat'

    <Chat
    renderDay={(props: DayProps) => (
    <Day {...props} wrapperStyle={{ backgroundColor: '#eee' }} textProps={{ style: { color: '#333' } }} />
    )}
    />

    isAnimated is true for the floating header that sticks to the top while scrolling and false for the inline separators, so one function can style them differently.

  • renderTime (Component | Function) - Custom time inside a message

  • timeTextStyle (Object) - Custom text style for time inside messages (supports left/right styles)

  • isDayAnimationEnabled (Bool) - Enable animated day label that appears on scroll; default is true

System Messages

  • renderSystemMessage (Component | Function) - Custom system message
Load earlier, typing indicator, quick replies, scroll to bottom

Load Earlier Messages

  • loadEarlierMessagesProps (Object) - Props to pass to the LoadEarlierMessages component. The button is only visible when isAvailable is true:
    • isAvailable - Controls button visibility (default: false)
    • onPress - Callback when button is pressed
    • isLoading - Display loading indicator (default: false)
    • isInfiniteScrollEnabled - Enable infinite scroll up when reaching the top of messages container, automatically calls onPress (not yet supported for web)
    • label - Override the default "Load earlier messages" text
    • containerStyle / wrapperStyle / textStyle - Custom styles for the button
    • activityIndicatorStyle - Custom style for the loading indicator
    • activityIndicatorColor - Color of the loading indicator (default: 'white')
    • activityIndicatorSize - Size of the loading indicator (default: 'small')
  • renderLoadEarlier (Component | Function) - Custom "Load earlier messages" button

Typing Indicator

  • isTyping (Bool) - Typing Indicator state; default false. If you use renderFooter it will override this.
  • renderTypingIndicator (Component | Function) - Custom typing indicator component
  • typingIndicatorStyle (StyleProp) - Custom style for the TypingIndicator component.
  • renderFooter (Component | Function) - Custom footer component on the ListView, e.g. 'User is typing...'; see CustomizedRenderingExample.tsx for an example. Overrides default typing indicator that triggers when isTyping is true.

Quick Replies

See the quick replies example in messages.ts.

  • onQuickReply (Function) - Callback when sending a quick reply (to backend server)
  • renderQuickReplies (Function) - Custom all quick reply view
  • quickReplyStyle (StyleProp) - Custom quick reply view style
  • quickReplyTextStyle (StyleProp) - Custom text style for quick reply buttons
  • quickReplyContainerStyle (StyleProp) - Custom container style for quick replies
  • renderQuickReplySend (Function) - Custom quick reply send view

Scroll to Bottom

  • isScrollToBottomEnabled (Bool) - Enables the scroll to bottom Component (Default is false)
  • scrollToBottomComponent (Function) - Custom Scroll To Bottom Component container
  • scrollToBottomOffset (Integer) - Custom Height Offset upon which to begin showing Scroll To Bottom Component (Default is 200)
  • scrollToBottomStyle (Object) - Custom style for Scroll To Bottom wrapper (position, bottom, right, etc.)
  • scrollToBottomContentStyle (Object) - Custom style for Scroll To Bottom content (size, background, shadow, etc.)