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 / bubble / wallpaper / nameColors). Deep-merged over defaultLightTheme; any subset is allowed. See Theming & Dark Mode.
  • renderWallpaper (Function | null) - The chat background. By default Chat draws a swirl gradient from theme.wallpaper, turning one step per message you send. Return your own element (an image, ChatWallpaper with other props...) to replace it, or pass null for the plain theme.colors.background.
  • 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 (LegendListRef) - Ref to the message list, a Legend List ref: scrollToEnd, scrollToKey (keys are message _ids as strings), scrollToIndex, getState. Indexes count from the oldest message
  • textInputRef (TextInput ref) - Ref to the text input
  • chatRef (ChatHandle ref) - chatRef.current.scrollToMessage(id, { animated, viewPosition, isHighlighted }) scrolls to a message, also one far up the history, and with isHighlighted flashes it the way a tapped quote does. For a search result or a deep link
Keyboard & layout

Keyboard & Layout​

  • bottomInset (Number) - The composer's space for the home indicator; measured by default. Pass it when the host already knows it, e.g. a chat inside a sliding panel whose own inset arrives late. It is still given up while the keyboard or the emoji panel covers it

  • 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.

  • 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
  • onDraftChange (Function) - (draft: string) => void, the user's unsent text as it changes ('' once sent). Editing a message sets the draft aside and brings it back afterwards, without reporting the edited text. Save it with the chat and pass it back as initialText
  • isSendButtonAlwaysVisible (Bool) - Always show send button in input text composer, disabled while there is nothing to send. By default it shows only with text when voice or video notes can be recorded (their button takes the slot while the composer is empty), and always when neither can
  • 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
  • emojiKeyboard (Bool | Object) - The built-in emoji keyboard behind the composer's emoji button, on by default. It opens in the system keyboard's place at the last keyboard height (200 + the bottom inset before a keyboard was seen) and inserts at the caret, whether or not you control text. false hides the emoji button. An object configures it: { isEnabled?, columns?, categories?, recents?, isSearchEnabled?, renderEmojiKeyboard? } - columns fixes the column count (default: as many 45pt columns as fit); categories picks and orders the tabs ('smileys' | 'animals' | 'food' | 'activities' | 'travel' | 'objects' | 'symbols' | 'flags'); recents is false or { isEnabled?, storageKey?, isPersisted? } (persisted through @react-native-async-storage/async-storage when installed); isSearchEnabled (default true); renderEmojiKeyboard({ onSelect, onBackspace, onClose, height, bottomInset }) draws your own keyboard in the panel. Colors and sizes live in theme.emojiKeyboard.
  • onPressEmoji (Function) - Called when the emoji button is pressed, instead of opening the built-in emoji keyboard. Passing it shows the button even with emojiKeyboard={false}.
  • audioRecording (Bool | Object) - Hold-to-record voice notes, on by default when expo-audio is installed; false (or { isEnabled: false }) turns them off. An object configures them: { isEnabled?, minDurationMs?, maxDurationMs?, isViewOnceEnabled?, onPermissionDenied?, onTooShort?, onError? }. isViewOnceEnabled shows a view-once toggle above the pause button while a take is locked or paused; a take sent with it on reaches onSend with isViewOnce: true. minDurationMs (default 700) drops takes that long or shorter and calls onTooShort; maxDurationMs (default 600000) sends the take when reached. Requires the optional expo-audio peer (and react-native-audio-api for the playback waveform); the mic button is hidden when it is absent. A paused take can be resumed when react-native-audio-api is installed with FFmpeg (the M4A recordings are joined without re-encoding), and trimmed when expo-file-system is installed too; a trimmed take reaches onSend as a 16-bit mono WAV at 24kHz, an untrimmed one as the recorder's M4A.
  • videoRecording (Bool | Object) - Round video notes, on by default when react-native-vision-camera is installed; false (or { isEnabled: false }) turns them off. true / { isEnabled: true } also offers the system-camera fallback below when vision-camera is missing. An object configures them: { isEnabled?, maxDuration?, minDurationMs?, isViewOnceEnabled?, onPermissionDenied?, onTooShort?, onError? }. maxDuration is in seconds (default 60); minDurationMs (default 800) drops shorter takes and calls onTooShort; isViewOnceEnabled works as in audioRecording, for round notes recorded with vision-camera. With react-native-vision-camera 5 or newer linked (plus its react-native-nitro-modules and react-native-nitro-image peers; it has no Expo config plugin, so add NSCameraUsageDescription/NSMicrophoneUsageDescription and the CAMERA/RECORD_AUDIO permissions yourself), the record button records a note on the first hold - shared with voice notes when both are enabled, on its own otherwise. Reaching maxDuration stops into a preview (sends directly without expo-video). Without vision-camera it falls back to expo-image-picker's system camera, which sends a plain (non-round) video.
  • mediaPlayback (Object) - How voice and round video notes play. { isAutoPlayNextEnabled?, playbackRate?, onPlaybackRateChange?, isRoundVideoAutoplayEnabled?, isNowPlayingBarEnabled?, isFloatingRoundNoteEnabled?, onMediaRead?, isNearEar?, onTranscribe?, onViewOnceEnd? }. isNowPlayingBarEnabled (default true) shows a "now playing" bar at the top of the chat while a note plays or is paused. isFloatingRoundNoteEnabled (default true) keeps a round note that is playing or paused going in a small draggable circle over the list once its row scrolls out of view; set it to false to stop the note with its row instead. isAutoPlayNextEnabled (default true) starts the next newer voice or round note in the chat when one plays to its end. The playback speed is shared by every note; playbackRate sets it, and onPlaybackRateChange reports changes so the app can keep the speed across launches. isRoundVideoAutoplayEnabled (default false) loops round notes silently in the list instead of holding their first frame. onMediaRead(message) is called when an incoming note with isMediaUnread starts playing, so the app can mark it listened. isNearEar is raise to listen: feed it from the app's proximity sensor, and while it is true the current voice or round note plays through the earpiece (restarting if it was under a second in); when it goes back to false the note pauses and the speaker route returns. onTranscribe(message) shows a transcribe button on voice notes and beside round notes; tapping it calls this, shows a loading outline until the app sets message.transcription, then opens the text under the waveform, or in a bubble under the round note (tap again to collapse or expand). onViewOnceEnd(message) is called once a view-once note (isViewOnce) has played to its end or been stopped after starting, so the app can remove it. A view-once round note carries the "1" marker on its play button, never autoplays or floats, and cannot be scrubbed.
  • 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​

  • attachments (Bool | Object) - The built-in attachment menu behind the composer's paperclip, on by default; the paperclip shows when at least one tab's peer is installed. Tabs: gallery (an in-sheet grid with expo-media-library, the system picker with expo-image-picker otherwise), camera (expo-image-picker; a tab of its own only without the grid, which has a camera tile), file (expo-document-picker) and location (expo-location). Picks are sent through onSend: one image / video message per photo or video with the caption on the first, a file message per document, a location message. false hides the paperclip. An object configures it: { isEnabled?, tabs?, pickers?, onPick?, renderAttachmentMenu? } - tabs picks and orders them; pickers ({ gallery?, camera?, file? }, each an async () => PickedAttachment[] that returns [] on cancel) replaces the Expo pickers with your own, for an app that picks with other libraries, and shows that tab without its Expo peer; isGalleryGridEnabled: false leaves Gallery to the system picker instead of the in-sheet grid, for an app without Android's READ_MEDIA_IMAGES / READ_MEDIA_VIDEO; onPick(attachments, { caption }) intercepts the picks (PickedAttachment[]) and returns the messages to send, null to send nothing, or nothing for the default; renderAttachmentMenu({ visible, onClose, tabs, onSend }) draws your own menu. Colors live in theme.attachments. actions, onPressActionButton and renderActions take precedence. See Emoji keyboard and attachment menu for the permissions each peer needs.
  • actions (Array) - Action options for the composer "+" button. Array of { title, action }; add icon (and optional color) to an action to render an 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 while the chat measures its layout on mount
  • isLoading (Boolean) - The history is loading. Over an empty list the chat shows a spinner in a service-colored circle (a 28 arc in a 36 circle, growing in from 0.3 over 150ms) in place of the empty-chat card. Messages already passed stay visible, without the spinner
  • mediaTransfer (Object) - Handlers for the media transfer buttons. { onDownload?, onCancel? }. A message with transfer: { type, progress?, totalBytes? } draws the progress ring with a cancel ✕ over its photo, video, file, voice or round note (with "1.2 MB / 4.5 MB" when totalBytes or the file size is known); tapping it calls onCancel(message). A message with isDownloadRequired draws the download arrow; tapping it calls onDownload(message). Without onDownload, a voice note or photo then fetches itself. Remote voice notes, photos and round notes that need no app handling show the same ring while they load, from the request's own progress
  • renderChatEmpty (Function | null) - What to show while there are no messages. By default a greeting card: "No messages here yet...", a line of help and a big 👋 that sends itself when tapped, centered over the wallpaper. Return your own element to replace it, or pass null for nothing. The card is exported as ChatEmpty.
  • emptyChatGreeting (String | null) - The greeting on the empty-chat card, sent as a message when tapped; default '👋'. null keeps just the title.
  • firstUnreadMessageId (String | Number | null) - The first message the user has not read. A full-width "Unread Messages" bar is drawn above it and the chat opens scrolled so the bar is at the top. Keep it fixed while the chat is open (the bar stays until you leave), e.g. computed once from the unread count when the screen mounts.
  • renderUnreadSeparator (Function | null) - Custom "Unread Messages" bar, or null to only scroll to the first unread message. The default is exported as UnreadSeparator.
  • renderChatFooter (Component | Function) - Custom component to render below the MessagesContainer (separate from the ListView)
  • listProps (Object) - Extra props for the message list, an AnimatedLegendList (e.g. drawDistance, maintainScrollAtEnd, onViewableItemsChanged). The list renders oldest first, not inverted, so onEndReached fires at the newest message. Handlers the list uses itself (onScrollBeginDrag / onScrollEndDrag, onMomentumScrollBegin / onMomentumScrollEnd, onContentSizeChange, onItemSizeChanged, onMetricsChange, onLayout, the viewability callbacks) run after its own, and contentContainerStyle goes on top of its padding.

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. The built-in one opens the photo viewer on tap: it pages through every photo in the chat, oldest first, with a "3 of 12" counter, the caption, sender and date; pinch or double-tap zooms, and a swipe up or down closes it
  • 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
  • renderMessageFile (Component | Function) - Custom renderer for IMessage.file; defaults to a document bubble (a circle with the extension, the name, the size) that opens the file in the share sheet (expo-sharing) or through Linking on tap
  • messageActions (Array | Function(message, defaults)) - Long-press context menu actions. Each item is { key?, label, icon?, onPress, destructive? }. An array replaces the built-in actions; a function receives the message and the built-in actions for it and returns what to show, so you can extend, filter or reorder them. See Message actions.
  • defaultMessageActions (Bool | MessageActionKey[]) - The built-in actions, in this order: reply, copy, forward, pin, edit, select, delete. Default true (all that can work); an array picks and orders them; false turns them off. Each shows only when it can work: Reply when reply.isEnabled is not false; Copy for messages with text when expo-clipboard or @react-native-clipboard/clipboard is installed; Edit on your own text messages when onEditMessage is set; Forward / Pin / Delete when their callbacks are set; Select when a selection can be acted on (a clipboard, Forward or Delete). They are also off when onLongPressMessage is set and messageActions is not, so an app that handles long-press itself keeps doing so.
  • onEditMessage (Function(message, text)) - Turns on the "Edit" action for your own text messages. Edit puts the text in the composer under an "Editing" banner; sending then calls this instead of onSend. Closing the banner cancels the edit.
  • onDeleteMessage (Function(message)) - Turns on the "Delete" action (not red).
  • onRetryMessage (Function(message)) - Turns on "Retry" for your own messages that failed to send (isFailed), first in their menu above Delete, whatever defaultMessageActions lists.
  • highlightText (String) / highlightTextStyle (TextStyle) - Words to mark in every message's text, links included (case-insensitive), e.g. the query of a search in the chat; yellow behind black text by default.
  • onForwardMessage (Function(message)) - Turns on the "Forward" action.
  • onForwardMessages (Function(messages)) - Forwards the messages checked in selection mode, oldest first (also turns on "Forward"). Without it the selection bar's Forward calls onForwardMessage once per message.
  • onDeleteMessages (Function(messages)) - Deletes the messages checked in selection mode, oldest first (also turns on "Delete"). Without it the selection bar's Delete calls onDeleteMessage once per message.
  • onSelectionChange (Function(messages)) - Multi-select: "Select" in the long-press menu checks the message, a tap checks or unchecks others (check circles on the left, a tinted row), and a bar replaces the composer with the count, Copy (texts joined oldest first), Forward and Delete. Called on every change with the checked messages; with [] once it ends (the X, Android's back, or the last message unchecked).
  • renderSelectionBar (Function({ count, actions, onClose, messages }) | null) - Custom bar in the composer's place while selecting, or null to keep the composer and drive the selection from your own header through onSelectionChange.
  • fetchLinkPreview (Function(url) => Promise<LinkPreview | null>) - A web page preview (accent bar, site name, bold title, description, picture full width or as a 48dp thumbnail) is drawn under the text for any message with linkPreview data. For messages without it, this fetches one for the first link in the text, e.g. from your server's Open Graph endpoint; each URL is fetched once per app run. IMessage.linkPreview: null turns it off for one message.
  • renderLinkPreview (Function({ preview, currentMessage, position, maxWidth, onPress }) | null) - Custom link preview, or null to draw none. The default is exported as LinkPreviewCard.
  • onPressLinkPreview (Function(preview, message)) - Called when a link preview is tapped, instead of opening its URL.
  • onPinMessage (Function(message)) - Turns on the "Pin" action; it reads "Unpin" on a message with isPinned: true. Toggle isPinned in the handler.
  • 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). Setting it (without messageActions) turns the built-in long-press menu off
  • 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​

Avatars and sender names show in group chats only: a one-to-one chat has neither.

  • isGroupChat (Bool) - Whether this is a group chat; default is auto-detected (more than one other sender in messages means a group)
  • isAvatarVisible (Bool) - Show avatars beside incoming messages; default true in group chats, false in one-to-one chats, and true whenever renderAvatar is a function. Pass true to keep avatars in one-to-one chats
  • 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) - Show the sender's name on the first message of each run of incoming messages; default true in group chats and false in one-to-one chats (see isGroupChat)
  • 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 - Shows a loading cell, a spinner in a 36 service circle, in place of the button (default: false)
    • isInfiniteScrollEnabled - Enable infinite scroll up when reaching the top of messages container, automatically calls onPress (not yet supported for web). The list then ends in the loading cell instead of a button while isAvailable
    • 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 spinner's arc (default: the date pill's text color)
    • activityIndicatorSize - Deprecated and ignored: the spinner is a fixed 28 arc
  • 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; the indicator comes as the second argument, renderFooter(props, typingIndicator), to keep it next to your own footer.
  • TypingStatus (Component) - The messenger way to show it: in your chat header, three dots that swell in turn before "typing" (waves for a recording, arrows for an upload). <TypingStatus users={typingUsers} action='recordingVoice' isGroup color={accent} /> reads "typing", "Anna is typing", "Anna and Max are typing", "recording a voice message"... ChatList rows use it for typingUsers / typingAction, and getTypingText gives the text alone

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​

The button comes up after you scroll back towards the newest message by scrollToBottomOffset, or when a message arrives while you are away from the newest one, and goes away at the newest message (or after scrolling away again by the same distance, when scrolling brought it up). Messages that arrive while you are away are counted in a badge, which counts down as each one scrolls into view.

  • isScrollToBottomEnabled (Bool) - Show the scroll-to-bottom button; default true. Passing true explicitly also keeps the older behaviour of a non-inverted list scrolling to its end on layout
  • isScrollToBottomBadgeEnabled (Bool) - Count new messages in a badge on the button; default true
  • scrollToBottomComponent (Function) - Custom Scroll To Bottom Component container
  • scrollToBottomOffset (Integer) - How far to scroll before the button shows or hides; default 100
  • 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.)