react-native-gifted-chat 3.2.3 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,33 +1,45 @@
1
- <h3 align="center">
2
- đŸ’Ŧ Gifted Chat
3
- </h3>
4
1
  <p align="center">
5
- The most complete chat UI for React Native & Web
6
- </p>
7
- <p align="center">
8
- <a href="https://www.npmjs.com/package/react-native-gifted-chat">
9
- <img alt="npm downloads" src="https://img.shields.io/npm/dm/react-native-gifted-chat.svg"/></a>
10
2
  <a href="https://www.npmjs.com/package/react-native-gifted-chat"><img alt="npm version" src="https://badge.fury.io/js/react-native-gifted-chat.svg"/></a>
11
-  <a href="https://circleci.com/gh/FaridSafi/react-native-gifted-chat"><img src="https://circleci.com/gh/FaridSafi/react-native-gifted-chat.svg?style=shield" alt="build"></a>
3
+ <a href="https://www.npmjs.com/package/react-native-gifted-chat"><img alt="npm downloads" src="https://img.shields.io/npm/dm/react-native-gifted-chat.svg"/></a>
4
+ <a href="https://circleci.com/gh/FaridSafi/react-native-gifted-chat"><img src="https://circleci.com/gh/FaridSafi/react-native-gifted-chat.svg?style=shield" alt="build"></a>
5
+ <img src="https://img.shields.io/badge/platforms-iOS%20%7C%20Android%20%7C%20Web-lightgrey.svg" alt="platforms">
6
+ <img src="https://img.shields.io/badge/TypeScript-supported-blue.svg" alt="TypeScript">
7
+ <img src="https://img.shields.io/badge/Expo-compatible-000020.svg" alt="Expo compatible">
12
8
  </p>
13
9
 
14
- ---
10
+ <h1 align="center">React Native Gifted Chat</h1>
15
11
 
16
- <h3 align="center">
17
- 🚀 Try it now in your browser!
18
- </h3>
19
12
  <p align="center">
20
- <a href="https://snack.expo.dev/@kesha-antonov/gifted-chat-playground" target="_blank">
21
- <img src="https://img.shields.io/badge/â–ļī¸_Try_GiftedChat_Playground-4630EB?style=for-the-badge&logo=expo&logoColor=white" alt="Try GiftedChat on Expo Snack"/>
22
- </a>
13
+ The most complete chat UI for React Native & Web
23
14
  </p>
15
+
24
16
  <p align="center">
25
- <strong>No installation required â€ĸ Interactive examples â€ĸ Edit and run in real-time</strong>
17
+ <a href="https://snack.expo.dev/@kesha-antonov/gifted-chat-playground" target="_blank">
18
+ <img src="https://img.shields.io/badge/â–ļī¸_Try_in_Browser-4630EB?style=for-the-badge&logo=expo&logoColor=white" alt="Try GiftedChat on Expo Snack"/>
19
+ </a>
26
20
  </p>
27
21
 
28
- <br />
22
+ ---
29
23
 
30
- <!-- previews -->
24
+ ## ✨ Features
25
+
26
+ - 🎨 **Fully Customizable** - Override any component with your own implementation
27
+ - 📎 **Composer Actions** - Attach photos, files, or trigger custom actions
28
+ - â†Šī¸ **Reply to Messages** - Swipe-to-reply with reply preview and message threading
29
+ - âŽī¸ **Load Earlier Messages** - Infinite scroll with pagination support
30
+ - 📋 **Copy to Clipboard** - Long-press messages to copy text
31
+ - 🔗 **Smart Link Parsing** - Auto-detect URLs, emails, phone numbers, hashtags, mentions
32
+ - 👤 **Avatars** - User initials or custom avatar images
33
+ - 🌍 **Localized Dates** - Full i18n support via Day.js
34
+ - âŒ¨ī¸ **Keyboard Handling** - Smart keyboard avoidance for all platforms
35
+ - đŸ’Ŧ **System Messages** - Display system notifications in chat
36
+ - ⚡ **Quick Replies** - Bot-style quick reply buttons
37
+ - âœī¸ **Typing Indicator** - Show when users are typing
38
+ - ✅ **Message Status** - Tick indicators for sent/delivered/read states
39
+ - âŦ‡ī¸ **Scroll to Bottom** - Quick navigation button
40
+ - 🌐 **Web Support** - Works with react-native-web
41
+ - 📱 **Expo Support** - Easy integration with Expo projects
42
+ - 📝 **TypeScript** - Complete TypeScript definitions included
31
43
 
32
44
  <p align="center">
33
45
  <img width="200" src="https://github.com/user-attachments/assets/c9da88f5-0b20-471c-8cd7-373bdb767517" />
@@ -39,124 +51,84 @@
39
51
 
40
52
  ---
41
53
 
42
- ## Features
43
-
44
- - Fully customizable components
45
- - Composer actions (to attach photos, etc.)
46
- - Load earlier messages
47
- - Copy messages to clipboard
48
- - Touchable links with customizable parsing (URLs, emails, phone numbers, hashtags, mentions)
49
- - Avatar as user's initials
50
- - Localized dates
51
- - Multi-line TextInput
52
- - InputToolbar avoiding keyboard
53
- - System message
54
- - Quick Reply messages (bot)
55
- - Typing indicator
56
- - Ticks indicator to display message status ( delivered, read )
57
- - Scroll to bottom button
58
- - react-native-web [web configuration](#react-native-web)
59
-
60
- ## Sponsor
54
+ ## 📖 Table of Contents
55
+
56
+ - [Features](#-features)
57
+ - [Requirements](#-requirements)
58
+ - [Installation](#-installation)
59
+ - [Usage](#-usage)
60
+ - [Props Reference](#-props-reference)
61
+ - [Data Structure](#-data-structure)
62
+ - [Platform Notes](#-platform-notes)
63
+ - [Example App](#-example-app)
64
+ - [Troubleshooting](#-troubleshooting)
65
+ - [Contributing](#-contributing)
66
+ - [Authors](#-authors)
67
+ - [License](#-license)
61
68
 
62
- <p align="center">
63
- <br/>
64
- <a href="https://www.lereacteur.io" target="_blank">
65
- <img src="https://raw.githubusercontent.com/FaridSafi/react-native-gifted-chat/master/media/logo_sponsor.png" height="60">
66
- </a>
67
- <br>
68
- <p align="center">
69
- Coding Bootcamp in Paris co-founded by Farid Safi
70
- </p>
71
- <a href="https://www.lereacteur.io" target="_blank">
72
- <p align="center">
73
- Click to learn more
74
- </p>
75
- </a>
76
- </p>
69
+ ---
77
70
 
78
- <p align="center">
79
- <br/>
80
- <a href="https://getstream.io/chat/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">
81
- <img src="https://raw.githubusercontent.com/FaridSafi/react-native-gifted-chat/master/media/stream-logo.png" height="40">
82
- </a>
83
- <br>
84
- <p align="center">
85
- Scalable <a href="https://getstream.io/chat/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">chat API/Server</a> written in Go
86
- </p>
87
- <p align="center">
88
- <a href="https://getstream.io/chat/get_started/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">API Tour</a> | <a href="https://dev.to/nickparsons/react-native-chat-with-chuck-norris-3h7m?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">React Native Gifted tutorial</a>
89
- </p>
90
- </p>
71
+ ## 📋 Requirements
91
72
 
92
- <p align="center">
93
- <br/>
94
- <a href="https://www.ethora.com" target="_blank">
95
- <img src="https://www.dappros.com/wp-content/uploads/2023/12/Ethora-Logo.png" height="60">
96
- </a>
97
- <br>
98
- <p align="center">
99
- A complete app engine featuring GiftedChat
100
- </p>
101
- <p align="center">
102
- <a href="https://bit.ly/ethorachat" target="_blank">Check out our GitHub</a>
103
- </p>
104
- </p>
105
- <br>
106
- <p align="center">
107
- <a href="https://amzn.to/3ZmTyb2" target="_blank">React Key Concepts: Consolidate your knowledge of React’s core features (2nd ed. Edition)</a>
108
- </p>
73
+ | Requirement | Version |
74
+ |-------------|---------|
75
+ | React Native | >= 0.70.0 |
76
+ | iOS | >= 13.4 |
77
+ | Android | API 21+ (Android 5.0) |
78
+ | Expo | SDK 50+ |
79
+ | TypeScript | >= 5.0 (optional) |
109
80
 
110
- # Getting started
81
+ ---
111
82
 
112
- ## Installation
83
+ ## đŸ“Ļ Installation
113
84
 
114
- ### Install dependencies
85
+ ### Expo Projects
115
86
 
116
- Yarn:
117
87
  ```bash
118
- yarn add react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
88
+ npx expo install react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
119
89
  ```
120
90
 
121
- Npm:
91
+ ### Bare React Native Projects
92
+
93
+ **Step 1:** Install the packages
122
94
 
95
+ Using yarn:
123
96
  ```bash
124
- npm install --save react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
97
+ yarn add react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
125
98
  ```
126
99
 
127
- Expo
100
+ Using npm:
128
101
  ```bash
129
- npx expo install react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
102
+ npm install --save react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
130
103
  ```
131
104
 
132
- ### Non-expo users
105
+ **Step 2:** Install iOS pods
133
106
 
134
107
  ```bash
135
108
  npx pod-install
136
109
  ```
137
110
 
138
- ### Setup react-native-reanimated
111
+ **Step 3:** Configure react-native-reanimated
139
112
 
140
- Follow guide: [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin)
113
+ Follow the [react-native-reanimated installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin) to add the Babel plugin.
114
+
115
+ ---
141
116
 
142
- ## Examples
117
+ ## 🚀 Usage
143
118
 
144
- ### Basic usage
119
+ ### Basic Example
145
120
 
146
121
  ```jsx
147
122
  import React, { useState, useCallback, useEffect } from 'react'
148
- import { Platform } from 'react-native'
149
123
  import { GiftedChat } from 'react-native-gifted-chat'
150
- import { useSafeAreaInsets } from 'react-native-safe-area-context'
124
+ import { useHeaderHeight } from '@react-navigation/elements'
151
125
 
152
126
  export function Example() {
153
127
  const [messages, setMessages] = useState([])
154
- const insets = useSafeAreaInsets()
155
128
 
156
- // If you have a tab bar, include its height
157
- const tabbarHeight = 50
158
- const keyboardTopToolbarHeight = Platform.select({ ios: 44, default: 0 })
159
- const keyboardVerticalOffset = insets.bottom + tabbarHeight + keyboardTopToolbarHeight
129
+ // keyboardVerticalOffset = distance from screen top to GiftedChat container
130
+ // useHeaderHeight() returns status bar + navigation header height
131
+ const headerHeight = useHeaderHeight()
160
132
 
161
133
  useEffect(() => {
162
134
  setMessages([
@@ -186,22 +158,51 @@ export function Example() {
186
158
  user={{
187
159
  _id: 1,
188
160
  }}
189
-
190
- keyboardAvoidingViewProps={{ keyboardVerticalOffset }}
161
+ keyboardAvoidingViewProps={{ keyboardVerticalOffset: headerHeight }}
191
162
  />
192
163
  )
193
164
  }
194
165
  ```
195
166
 
196
- ### Other examples
167
+ > **💡 Tip:** Check out more examples in the [`example`](example) directory including Slack-style messages, quick replies, and custom components.
168
+
169
+ ---
170
+
171
+ ## 📊 Data Structure
172
+
173
+ Messages, system messages, and quick replies follow the structure defined in [Models.ts](src/Models.ts).
174
+
175
+ <details>
176
+ <summary><strong>Message Object Structure</strong></summary>
197
177
 
198
- Check out code of [`examples`](example)
178
+ ```typescript
179
+ interface IMessage {
180
+ _id: string | number
181
+ text: string
182
+ createdAt: Date | number
183
+ user: User
184
+ image?: string
185
+ video?: string
186
+ audio?: string
187
+ system?: boolean
188
+ sent?: boolean
189
+ received?: boolean
190
+ pending?: boolean
191
+ quickReplies?: QuickReplies
192
+ }
193
+
194
+ interface User {
195
+ _id: string | number
196
+ name?: string
197
+ avatar?: string | number | (() => React.ReactNode)
198
+ }
199
+ ```
199
200
 
200
- ## Data structure
201
+ </details>
201
202
 
202
- Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
203
+ ---
203
204
 
204
- ## Props
205
+ ## 📖 Props Reference
205
206
 
206
207
  ### Core Configuration
207
208
 
@@ -219,16 +220,51 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
219
220
 
220
221
  ### Keyboard & Layout
221
222
 
222
- - **`keyboardProviderProps`** _(Object)_ - Props to be passed to the [`KeyboardProvider`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-provider) for keyboard handling.
223
- - **`keyboardAvoidingViewProps`** _(Object)_ - Props to be passed to the [`KeyboardAvoidingView`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-avoiding-view). The `behavior` prop defaults to `'padding'`.
223
+ - **`keyboardProviderProps`** _(Object)_ - Props to be passed to the [`KeyboardProvider`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-provider) for keyboard handling. Default values:
224
+ - `statusBarTranslucent: true` - Required on Android for correct keyboard height calculation when status bar is translucent (edge-to-edge mode)
225
+ - `navigationBarTranslucent: true` - Required on Android for correct keyboard height calculation when navigation bar is translucent (edge-to-edge mode)
226
+ - **`keyboardAvoidingViewProps`** _(Object)_ - Props to be passed to the [`KeyboardAvoidingView`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view). See **keyboardVerticalOffset** below for proper keyboard handling.
224
227
  - **`isAlignedTop`** _(Boolean)_ Controls whether or not the message bubbles appear at the top of the chat (Default is false - bubbles align to bottom)
225
228
  - **`isInverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
226
229
 
230
+ #### Understanding `keyboardVerticalOffset`
231
+
232
+ The [`keyboardVerticalOffset`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view#keyboardverticaloffset) tells the KeyboardAvoidingView where its container starts relative to the top of the screen. This is essential when GiftedChat is not positioned at the very top of the screen (e.g., when you have a navigation header).
233
+
234
+ **Default value:** `insets.top` (status bar height from `useSafeAreaInsets()`). This works correctly only when GiftedChat fills the entire screen without a navigation header. If you have a navigation header, you need to pass the correct offset via `keyboardAvoidingViewProps`.
235
+
236
+ **What the value means:** The offset equals the distance (in points) from the top of the screen to the top of your GiftedChat container. This typically includes:
237
+ - Status bar height
238
+ - Navigation header height (on iOS, `useHeaderHeight()` already includes status bar)
239
+
240
+ **How to use:**
241
+
242
+ ```jsx
243
+ import { useHeaderHeight } from '@react-navigation/elements'
244
+
245
+ function ChatScreen() {
246
+ // useHeaderHeight() returns status bar + navigation header height on iOS
247
+ const headerHeight = useHeaderHeight()
248
+
249
+ return (
250
+ <GiftedChat
251
+ keyboardAvoidingViewProps={{ keyboardVerticalOffset: headerHeight }}
252
+ // ... other props
253
+ />
254
+ )
255
+ }
256
+ ```
257
+
258
+ > **Note:** `useHeaderHeight()` requires your chat component to be rendered inside a proper navigation screen (not conditional rendering). If it returns `0`, ensure your chat screen is a real navigation screen with a visible header.
259
+
260
+ **Why this matters:** Without the correct offset, the keyboard may overlap the input field or leave extra space. The KeyboardAvoidingView uses this value to calculate how much to shift the content when the keyboard appears.
261
+
227
262
  ### Text Input & Composer
228
263
 
229
264
  - **`text`** _(String)_ - Input text; default is `undefined`, but if specified, it will override GiftedChat's internal state. Useful for managing text state outside of GiftedChat (e.g. with Redux). Don't forget to implement `textInputProps.onChangeText` to update the text state.
230
265
  - **`initialText`** _(String)_ - Initial text to display in the input field
231
266
  - **`isSendButtonAlwaysVisible`** _(Bool)_ - Always show send button in input text composer; default `false`, show only when text input is not empty
267
+ - **`isTextOptional`** _(Bool)_ - Allow sending messages without text (useful for media-only messages); default `false`. Use with `isSendButtonAlwaysVisible` for media attachments.
232
268
  - **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
233
269
  - **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
234
270
  - **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
@@ -253,7 +289,7 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
253
289
  - **`renderLoading`** _(Component | Function)_ - Render a loading view when initializing
254
290
  - **`renderChatEmpty`** _(Component | Function)_ - Custom component to render in the ListView when messages are empty
255
291
  - **`renderChatFooter`** _(Component | Function)_ - Custom component to render below the MessagesContainer (separate from the ListView)
256
- - **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist)
292
+ - **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist). Supports all FlatList props including `maintainVisibleContentPosition` for keeping scroll position when new messages arrive (useful for AI chatbots).
257
293
 
258
294
  ### Message Bubbles & Content
259
295
 
@@ -352,6 +388,10 @@ See full example in [LinksExample](example/components/chat-examples/LinksExample
352
388
  - **`dateFormat`** _(String)_ - Format to use for rendering dates; default is `'D MMMM'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
353
389
  - **`dateFormatCalendar`** _(Object)_ - Format to use for rendering relative times; default is `{ sameDay: '[Today]' }` (see [Day.js Calendar](https://day.js.org/docs/en/plugin/calendar))
354
390
  - **`renderDay`** _(Component | Function)_ - Custom day above a message
391
+ - **`dayProps`** _(Object)_ - Props to pass to the Day component:
392
+ - `containerStyle` - Custom style for the day container
393
+ - `wrapperStyle` - Custom style for the day wrapper
394
+ - `textProps` - Props to pass to the Text component (e.g., `style`, `allowFontScaling`, `numberOfLines`)
355
395
  - **`renderTime`** _(Component | Function)_ - Custom time inside a message
356
396
  - **`timeTextStyle`** _(Object)_ - Custom text style for time inside messages (supports left/right styles)
357
397
  - **`isDayAnimationEnabled`** _(Bool)_ - Enable animated day label that appears on scroll; default is `true`
@@ -394,46 +434,214 @@ See [Quick Replies example in messages.ts](example/example-expo/data/messages.ts
394
434
  - **`quickReplyContainerStyle`** _(StyleProp<ViewStyle>)_ - Custom container style for quick replies
395
435
  - **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
396
436
 
437
+ ### Reply to Messages
438
+
439
+ Gifted Chat supports swipe-to-reply functionality out of the box. When enabled, users can swipe on a message to reply to it, displaying a reply preview in the input toolbar and the replied message above the new message bubble.
440
+
441
+ > **Note:** This feature uses `ReanimatedSwipeable` from `react-native-gesture-handler` and `react-native-reanimated` for smooth, performant animations.
442
+
443
+ #### Basic Usage
444
+
445
+ ```tsx
446
+ <GiftedChat
447
+ messages={messages}
448
+ onSend={onSend}
449
+ user={{ _id: 1 }}
450
+ reply={{
451
+ swipe: {
452
+ isEnabled: true,
453
+ direction: 'left', // swipe left to reply
454
+ },
455
+ }}
456
+ />
457
+ ```
458
+
459
+ #### Reply Props (Grouped)
460
+
461
+ The `reply` prop accepts an object with the following structure:
462
+
463
+ ```typescript
464
+ interface ReplyProps<TMessage> {
465
+ // Swipe gesture configuration
466
+ swipe?: {
467
+ isEnabled?: boolean // Enable swipe-to-reply; default false
468
+ direction?: 'left' | 'right' // Swipe direction; default 'left'
469
+ onSwipe?: (message: TMessage) => void // Callback when swiped
470
+ renderAction?: ( // Custom swipe action component
471
+ progress: SharedValue<number>,
472
+ translation: SharedValue<number>,
473
+ position: 'left' | 'right'
474
+ ) => React.ReactNode
475
+ actionContainerStyle?: StyleProp<ViewStyle>
476
+ }
477
+
478
+ // Reply preview styling (above input toolbar)
479
+ previewStyle?: {
480
+ containerStyle?: StyleProp<ViewStyle>
481
+ textStyle?: StyleProp<TextStyle>
482
+ imageStyle?: StyleProp<ImageStyle>
483
+ }
484
+
485
+ // In-bubble reply styling
486
+ messageStyle?: {
487
+ containerStyle?: StyleProp<ViewStyle>
488
+ containerStyleLeft?: StyleProp<ViewStyle>
489
+ containerStyleRight?: StyleProp<ViewStyle>
490
+ textStyle?: StyleProp<TextStyle>
491
+ textStyleLeft?: StyleProp<TextStyle>
492
+ textStyleRight?: StyleProp<TextStyle>
493
+ imageStyle?: StyleProp<ImageStyle>
494
+ }
495
+
496
+ // Callbacks and state
497
+ message?: ReplyMessage // Controlled reply state
498
+ onClear?: () => void // Called when reply cleared
499
+ onPress?: (message: TMessage) => void // Called when reply preview tapped
500
+
501
+ // Custom renderers
502
+ renderPreview?: (props: ReplyPreviewProps) => React.ReactNode
503
+ renderMessageReply?: (props: MessageReplyProps) => React.ReactNode
504
+ }
505
+ ```
506
+
507
+ #### ReplyMessage Structure
508
+
509
+ When a message has a reply, it includes a `replyMessage` property:
510
+
511
+ ```typescript
512
+ interface ReplyMessage {
513
+ _id: string | number
514
+ text: string
515
+ user: User
516
+ image?: string
517
+ audio?: string
518
+ }
519
+ ```
520
+
521
+ #### Advanced Example with External State
522
+
523
+ ```tsx
524
+ const [replyMessage, setReplyMessage] = useState<ReplyMessage | null>(null)
525
+
526
+ <GiftedChat
527
+ messages={messages}
528
+ onSend={messages => {
529
+ const newMessages = messages.map(msg => ({
530
+ ...msg,
531
+ replyMessage: replyMessage || undefined,
532
+ }))
533
+ setMessages(prev => GiftedChat.append(prev, newMessages))
534
+ setReplyMessage(null)
535
+ }}
536
+ user={{ _id: 1 }}
537
+ reply={{
538
+ swipe: {
539
+ isEnabled: true,
540
+ direction: 'right',
541
+ onSwipe: setReplyMessage,
542
+ },
543
+ message: replyMessage,
544
+ onClear: () => setReplyMessage(null),
545
+ onPress: (msg) => scrollToMessage(msg._id),
546
+ }}
547
+ />
548
+ ```
549
+
550
+ #### Smooth Animations
551
+
552
+ The reply preview automatically animates when:
553
+ - **Appearing**: Smoothly expands from zero height with fade-in effect
554
+ - **Disappearing**: Smoothly collapses with fade-out effect
555
+ - **Content changes**: Smoothly transitions when replying to a different message
556
+
557
+ These animations use `react-native-reanimated` for 60fps performance.
558
+
397
559
  ### Scroll to Bottom
398
560
 
399
561
  - **`isScrollToBottomEnabled`** _(Bool)_ - Enables the scroll to bottom Component (Default is false)
400
562
  - **`scrollToBottomComponent`** _(Function)_ - Custom Scroll To Bottom Component container
401
563
  - **`scrollToBottomOffset`** _(Integer)_ - Custom Height Offset upon which to begin showing Scroll To Bottom Component (Default is 200)
402
- - **`scrollToBottomStyle`** _(Object)_ - Custom style for Bottom Component container
564
+ - **`scrollToBottomStyle`** _(Object)_ - Custom style for Scroll To Bottom wrapper (position, bottom, right, etc.)
565
+ - **`scrollToBottomContentStyle`** _(Object)_ - Custom style for Scroll To Bottom content (size, background, shadow, etc.)
403
566
 
404
- ## Notes for Android
567
+ ### Maintaining Scroll Position (AI Chatbots)
405
568
 
406
- If you are using Create React Native App / Expo, no Android specific installation steps are required -- you can skip this section. Otherwise, we recommend modifying your project configuration as follows.
569
+ For AI chat interfaces where long responses arrive and you don't want to disrupt the user's reading position, use [`maintainVisibleContentPosition`](https://reactnative.dev/docs/scrollview#maintainvisiblecontentposition) via `listProps`:
407
570
 
408
- - Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`:
571
+ ```tsx
572
+ // Basic usage - always maintain scroll position
573
+ <GiftedChat
574
+ listProps={{
575
+ maintainVisibleContentPosition: {
576
+ minIndexForVisible: 0,
577
+ },
578
+ }}
579
+ />
409
580
 
410
- ```xml
411
- <activity
412
- android:name=".MainActivity"
413
- android:label="@string/app_name"
414
- android:windowSoftInputMode="adjustResize"
415
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
416
- ```
581
+ // With auto-scroll threshold - auto-scroll if within 10 pixels of newest content
582
+ <GiftedChat
583
+ listProps={{
584
+ maintainVisibleContentPosition: {
585
+ minIndexForVisible: 0,
586
+ autoscrollToTopThreshold: 10,
587
+ },
588
+ }}
589
+ />
417
590
 
418
- - For **Expo**, there are at least 2 solutions to fix it:
591
+ // Conditionally enable based on scroll state (recommended for chatbots)
592
+ const [isScrolledUp, setIsScrolledUp] = useState(false)
419
593
 
420
- - Append [`KeyboardAvoidingView`](https://reactnative.dev/docs/keyboardavoidingview) after GiftedChat. This should only be done for Android, as `KeyboardAvoidingView` may conflict with the iOS keyboard avoidance already built into GiftedChat, e.g.:
594
+ <GiftedChat
595
+ listProps={{
596
+ onScroll: (event) => {
597
+ setIsScrolledUp(event.contentOffset.y > 50)
598
+ },
599
+ maintainVisibleContentPosition: isScrolledUp
600
+ ? { minIndexForVisible: 0, autoscrollToTopThreshold: 10 }
601
+ : undefined,
602
+ }}
603
+ />
604
+ ```
421
605
 
606
+ ---
607
+
608
+ ## 📱 Platform Notes
609
+
610
+ ### Android
611
+
612
+ <details>
613
+ <summary><strong>Keyboard configuration</strong></summary>
614
+
615
+ If you are using Create React Native App / Expo, no Android specific installation steps are required. Otherwise, we recommend modifying your project configuration:
616
+
617
+ Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`:
618
+
619
+ ```xml
620
+ <activity
621
+ android:name=".MainActivity"
622
+ android:label="@string/app_name"
623
+ android:windowSoftInputMode="adjustResize"
624
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
422
625
  ```
626
+
627
+ For **Expo**, you can append `KeyboardAvoidingView` after GiftedChat (Android only):
628
+
629
+ ```jsx
423
630
  <View style={{ flex: 1 }}>
424
631
  <GiftedChat />
425
- {
426
- Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />
427
- }
632
+ {Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />}
428
633
  </View>
429
634
  ```
430
635
 
431
- ## Notes for local development
636
+ </details>
637
+
638
+ ### Web (react-native-web)
432
639
 
433
- #### With create-react-app
640
+ <details>
641
+ <summary><strong>With create-react-app</strong></summary>
434
642
 
435
- 1. `yarn add -D react-app-rewired`
436
- 2. `touch config-overrides.js`
643
+ 1. Install react-app-rewired: `yarn add -D react-app-rewired`
644
+ 2. Create `config-overrides.js`:
437
645
 
438
646
  ```js
439
647
  module.exports = function override(config, env) {
@@ -453,23 +661,30 @@ module.exports = function override(config, env) {
453
661
  },
454
662
  },
455
663
  })
456
-
457
664
  return config
458
665
  }
459
666
  ```
460
667
 
461
- > You will find an example and a **web demo** here: [xcarpentier/gifted-chat-web-demo](https://github.com/xcarpentier/gifted-chat-web-demo)
668
+ > **Examples:**
669
+ > - [xcarpentier/gifted-chat-web-demo](https://github.com/xcarpentier/gifted-chat-web-demo)
670
+ > - [Gatsby example](https://github.com/xcarpentier/clean-archi-boilerplate/tree/develop/apps/web)
671
+
672
+ </details>
673
+
674
+ ---
675
+
676
+ ## đŸ§Ē Testing
462
677
 
463
- > Another example with **Gatsby** : [xcarpentier/clean-archi-boilerplate](https://github.com/xcarpentier/clean-archi-boilerplate/tree/develop/apps/web)
678
+ <details>
679
+ <summary><strong>Triggering layout events in tests</strong></summary>
464
680
 
465
- ## Testing
466
- `TEST_ID` is exported as constants that can be used in your testing library of choice
681
+ `TEST_ID` is exported as constants that can be used in your testing library of choice.
467
682
 
468
- Gifted Chat uses `onLayout` to determine the height of the chat container. To trigger `onLayout` during your tests, you can run the following bits of code.
683
+ Gifted Chat uses `onLayout` to determine the height of the chat container. To trigger `onLayout` during your tests:
469
684
 
470
685
  ```typescript
471
- const WIDTH = 200; // or any number
472
- const HEIGHT = 2000; // or any number
686
+ const WIDTH = 200
687
+ const HEIGHT = 2000
473
688
 
474
689
  const loadingWrapper = getByTestId(TEST_ID.LOADING_WRAPPER)
475
690
  fireEvent(loadingWrapper, 'layout', {
@@ -482,37 +697,144 @@ fireEvent(loadingWrapper, 'layout', {
482
697
  })
483
698
  ```
484
699
 
485
- ## Questions
700
+ </details>
701
+
702
+ ---
703
+
704
+ ## đŸ“Ļ Example App
705
+
706
+ The repository includes a comprehensive example app demonstrating all features:
707
+
708
+ ```bash
709
+ # Clone and install
710
+ git clone https://github.com/FaridSafi/react-native-gifted-chat.git
711
+ cd react-native-gifted-chat/example
712
+ yarn install
713
+
714
+ # Run on iOS
715
+ npx expo run:ios
716
+
717
+ # Run on Android
718
+ npx expo run:android
719
+
720
+ # Run on Web
721
+ npx expo start --web
722
+ ```
723
+
724
+ The example app showcases:
725
+ - đŸ’Ŧ Basic chat functionality
726
+ - 🎨 Custom message bubbles and avatars
727
+ - â†Šī¸ Reply to messages with swipe gesture
728
+ - ⚡ Quick replies (bot-style)
729
+ - âœī¸ Typing indicators
730
+ - 📎 Attachment actions
731
+ - 🔗 Link parsing and custom matchers
732
+ - 🌐 Web compatibility
733
+
734
+ ---
735
+
736
+ ## ❓ Troubleshooting
737
+
738
+ <details>
739
+ <summary><strong>TextInput is hidden on Android</strong></summary>
740
+
741
+ Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`. See [Android configuration](#android) above.
742
+
743
+ </details>
744
+
745
+ <details>
746
+ <summary><strong>How to set Bubble color for each user?</strong></summary>
486
747
 
487
- - [How can I set Bubble color for each user?](https://github.com/FaridSafi/react-native-gifted-chat/issues/672)
488
- - [How can I pass style props to InputToolbar design and customize its color and other styles properties?](https://github.com/FaridSafi/react-native-gifted-chat/issues/662)
489
- - [How can I change the color of the message box?](https://github.com/FaridSafi/react-native-gifted-chat/issues/640)
490
- - [Is there a way to manually dismiss the keyboard?](https://github.com/FaridSafi/react-native-gifted-chat/issues/647)
491
- - [I want to implement a popover that pops right after clicking on a specific avatar,
492
- what is the best implementation in this case and how?](https://github.com/FaridSafi/react-native-gifted-chat/issues/660)
493
- - [Why TextInput is hidden on Android?](https://github.com/FaridSafi/react-native-gifted-chat/issues/680#issuecomment-359699364)
494
- - [How to use renderLoading?](https://github.com/FaridSafi/react-native-gifted-chat/issues/298)
495
- - [Can I use MySql to save the message?](https://github.com/FaridSafi/react-native-gifted-chat/issues/738)
748
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/672) for examples.
496
749
 
497
- ## You have a question?
750
+ </details>
498
751
 
499
- 1. Please check this readme and you might find a response
500
- 1. Please ask on StackOverflow first: https://stackoverflow.com/questions/tagged/react-native-gifted-chat
501
- 1. Find responses in existing issues
502
- 1. Try to keep issues for issues
752
+ <details>
753
+ <summary><strong>How to customize InputToolbar styles?</strong></summary>
503
754
 
504
- ## Hire an expert
755
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/662) for examples.
505
756
 
506
- Looking for a React Native freelance expert with more than 14 years of experience? Contact Xavier from his [website](https://xaviercarpentier.com)
757
+ </details>
507
758
 
508
- ## Author
759
+ <details>
760
+ <summary><strong>How to manually dismiss the keyboard?</strong></summary>
761
+
762
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/647) for examples.
763
+
764
+ </details>
765
+
766
+ <details>
767
+ <summary><strong>How to use renderLoading?</strong></summary>
768
+
769
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/298) for examples.
770
+
771
+ </details>
772
+
773
+ ---
774
+
775
+ ## 🤔 Have a Question?
776
+
777
+ 1. Check this README first
778
+ 2. Search [existing issues](https://github.com/FaridSafi/react-native-gifted-chat/issues)
779
+ 3. Ask on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native-gifted-chat)
780
+ 4. Open a new issue if needed
781
+
782
+ ---
509
783
 
510
- Feel free to ask me questions on Twitter [@FaridSafi](https://www.x.com/FaridSafi) or [@xcapetir](https://www.x.com/xcapetir)
784
+ ## 🤝 Contributing
511
785
 
512
- ## Maintainer
786
+ Contributions are welcome! Please feel free to submit a Pull Request.
513
787
 
514
- Have any questions? Reach out to [Kesha Antonov](https://github.com/kesha-antonov)
788
+ 1. Fork the repository
789
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
790
+ 3. Install dependencies (`yarn install`)
791
+ 4. Make your changes
792
+ 5. Run tests (`yarn test`)
793
+ 6. Run linting (`yarn lint`)
794
+ 7. Build the library (`yarn build`)
795
+ 8. Commit your changes (`git commit -m 'Add amazing feature'`)
796
+ 9. Push to the branch (`git push origin feature/amazing-feature`)
797
+ 10. Open a Pull Request
515
798
 
516
- Please note that I'm maintaining this project in my free time for free. If you find any issues, feel free to open them, and I'll do my best to address them as time permits.
799
+ ### Development Setup
517
800
 
518
- If you consider my work helpful please consider [become a backer](https://github.com/sponsors/kesha-antonov), I'll have more time to work on open source. Thanks!
801
+ ```bash
802
+ # Install dependencies
803
+ yarn install
804
+
805
+ # Build the library
806
+ yarn build
807
+
808
+ # Run tests
809
+ yarn test
810
+
811
+ # Run linting
812
+ yarn lint
813
+
814
+ # Full validation
815
+ yarn prepublishOnly
816
+ ```
817
+
818
+ ---
819
+
820
+ ## đŸ‘Ĩ Authors
821
+
822
+ **Original Author:** [Farid Safi](https://www.x.com/FaridSafi)
823
+
824
+ **Co-maintainer:** [Xavier Carpentier](https://www.x.com/xcapetir) - [Hire Xavier](https://xaviercarpentier.com)
825
+
826
+ **Maintainer:** [Kesha Antonov](https://github.com/kesha-antonov)
827
+
828
+ > Please note that this project is maintained in free time. If you find it helpful, please consider [becoming a sponsor](https://github.com/sponsors/kesha-antonov).
829
+
830
+ ---
831
+
832
+ ## 📄 License
833
+
834
+ [MIT](LICENSE)
835
+
836
+ ---
837
+
838
+ <p align="center">
839
+ <sub>Built with â¤ī¸ by the React Native community</sub>
840
+ </p>