react-native-gifted-chat 3.2.2 → 3.3.0

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.
Files changed (42) hide show
  1. package/README.md +450 -156
  2. package/package.json +9 -8
  3. package/src/Bubble/index.tsx +34 -2
  4. package/src/Bubble/types.ts +17 -4
  5. package/src/Composer.tsx +1 -2
  6. package/src/Day/index.tsx +2 -2
  7. package/src/Day/types.ts +3 -2
  8. package/src/GiftedAvatar.tsx +1 -1
  9. package/src/GiftedChat/index.tsx +109 -23
  10. package/src/GiftedChat/types.ts +9 -3
  11. package/src/InputToolbar.tsx +62 -8
  12. package/src/Message/index.tsx +181 -21
  13. package/src/Message/types.ts +4 -0
  14. package/src/MessageReply.tsx +160 -0
  15. package/src/MessageText.tsx +2 -2
  16. package/src/MessagesContainer/components/DayAnimated/index.tsx +5 -1
  17. package/src/MessagesContainer/components/Item/index.tsx +82 -47
  18. package/src/MessagesContainer/index.tsx +30 -19
  19. package/src/MessagesContainer/styles.ts +2 -0
  20. package/src/MessagesContainer/types.ts +30 -3
  21. package/src/Models.ts +3 -0
  22. package/src/Reply/index.ts +1 -0
  23. package/src/Reply/types.ts +80 -0
  24. package/src/ReplyPreview.tsx +132 -0
  25. package/src/Send.tsx +8 -3
  26. package/src/SystemMessage.tsx +22 -16
  27. package/src/__tests__/MessageReply.test.tsx +54 -0
  28. package/src/__tests__/ReplyPreview.test.tsx +41 -0
  29. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +69 -42
  30. package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +11 -15
  31. package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +24 -18
  32. package/src/__tests__/__snapshots__/MessageReply.test.tsx.snap +181 -0
  33. package/src/__tests__/__snapshots__/ReplyPreview.test.tsx.snap +403 -0
  34. package/src/__tests__/__snapshots__/Send.test.tsx.snap +3 -0
  35. package/src/__tests__/__snapshots__/SystemMessage.test.tsx.snap +36 -25
  36. package/src/components/MessageReply.tsx +156 -0
  37. package/src/components/ReplyPreview.tsx +230 -0
  38. package/src/index.ts +6 -1
  39. package/src/types.ts +17 -16
  40. package/src/utils.ts +11 -3
  41. package/CHANGELOG.md +0 -364
  42. package/src/reanimatedCompat.ts +0 -27
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,109 +51,72 @@
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
112
+
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.
139
114
 
140
- Follow guide: [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin)
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'
@@ -193,15 +168,45 @@ export function Example() {
193
168
  }
194
169
  ```
195
170
 
196
- ### Other examples
171
+ > **💡 Tip:** Check out more examples in the [`example`](example) directory including Slack-style messages, quick replies, and custom components.
172
+
173
+ ---
174
+
175
+ ## 📊 Data Structure
197
176
 
198
- Check out code of [`examples`](example)
177
+ Messages, system messages, and quick replies follow the structure defined in [Models.ts](src/Models.ts).
199
178
 
200
- ## Data structure
179
+ <details>
180
+ <summary><strong>Message Object Structure</strong></summary>
201
181
 
202
- Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
182
+ ```typescript
183
+ interface IMessage {
184
+ _id: string | number
185
+ text: string
186
+ createdAt: Date | number
187
+ user: User
188
+ image?: string
189
+ video?: string
190
+ audio?: string
191
+ system?: boolean
192
+ sent?: boolean
193
+ received?: boolean
194
+ pending?: boolean
195
+ quickReplies?: QuickReplies
196
+ }
203
197
 
204
- ## Props
198
+ interface User {
199
+ _id: string | number
200
+ name?: string
201
+ avatar?: string | number | (() => React.ReactNode)
202
+ }
203
+ ```
204
+
205
+ </details>
206
+
207
+ ---
208
+
209
+ ## 📖 Props Reference
205
210
 
206
211
  ### Core Configuration
207
212
 
@@ -219,8 +224,10 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
219
224
 
220
225
  ### Keyboard & Layout
221
226
 
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'`.
227
+ - **`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:
228
+ - `statusBarTranslucent: true` - Required on Android for correct keyboard height calculation when status bar is translucent (edge-to-edge mode)
229
+ - `navigationBarTranslucent: true` - Required on Android for correct keyboard height calculation when navigation bar is translucent (edge-to-edge mode)
230
+ - **`keyboardAvoidingViewProps`** _(Object)_ - Props to be passed to the [`KeyboardAvoidingView`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view). Use `keyboardVerticalOffset` to account for headers or iOS predictive text bar (~50pt).
224
231
  - **`isAlignedTop`** _(Boolean)_ Controls whether or not the message bubbles appear at the top of the chat (Default is false - bubbles align to bottom)
225
232
  - **`isInverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
226
233
 
@@ -229,6 +236,7 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
229
236
  - **`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
237
  - **`initialText`** _(String)_ - Initial text to display in the input field
231
238
  - **`isSendButtonAlwaysVisible`** _(Bool)_ - Always show send button in input text composer; default `false`, show only when text input is not empty
239
+ - **`isTextOptional`** _(Bool)_ - Allow sending messages without text (useful for media-only messages); default `false`. Use with `isSendButtonAlwaysVisible` for media attachments.
232
240
  - **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
233
241
  - **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
234
242
  - **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
@@ -253,7 +261,7 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
253
261
  - **`renderLoading`** _(Component | Function)_ - Render a loading view when initializing
254
262
  - **`renderChatEmpty`** _(Component | Function)_ - Custom component to render in the ListView when messages are empty
255
263
  - **`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)
264
+ - **`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
265
 
258
266
  ### Message Bubbles & Content
259
267
 
@@ -352,6 +360,10 @@ See full example in [LinksExample](example/components/chat-examples/LinksExample
352
360
  - **`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
361
  - **`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
362
  - **`renderDay`** _(Component | Function)_ - Custom day above a message
363
+ - **`dayProps`** _(Object)_ - Props to pass to the Day component:
364
+ - `containerStyle` - Custom style for the day container
365
+ - `wrapperStyle` - Custom style for the day wrapper
366
+ - `textProps` - Props to pass to the Text component (e.g., `style`, `allowFontScaling`, `numberOfLines`)
355
367
  - **`renderTime`** _(Component | Function)_ - Custom time inside a message
356
368
  - **`timeTextStyle`** _(Object)_ - Custom text style for time inside messages (supports left/right styles)
357
369
  - **`isDayAnimationEnabled`** _(Bool)_ - Enable animated day label that appears on scroll; default is `true`
@@ -394,46 +406,214 @@ See [Quick Replies example in messages.ts](example/example-expo/data/messages.ts
394
406
  - **`quickReplyContainerStyle`** _(StyleProp<ViewStyle>)_ - Custom container style for quick replies
395
407
  - **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
396
408
 
409
+ ### Reply to Messages
410
+
411
+ 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.
412
+
413
+ > **Note:** This feature uses `ReanimatedSwipeable` from `react-native-gesture-handler` and `react-native-reanimated` for smooth, performant animations.
414
+
415
+ #### Basic Usage
416
+
417
+ ```tsx
418
+ <GiftedChat
419
+ messages={messages}
420
+ onSend={onSend}
421
+ user={{ _id: 1 }}
422
+ reply={{
423
+ swipe: {
424
+ isEnabled: true,
425
+ direction: 'left', // swipe left to reply
426
+ },
427
+ }}
428
+ />
429
+ ```
430
+
431
+ #### Reply Props (Grouped)
432
+
433
+ The `reply` prop accepts an object with the following structure:
434
+
435
+ ```typescript
436
+ interface ReplyProps<TMessage> {
437
+ // Swipe gesture configuration
438
+ swipe?: {
439
+ isEnabled?: boolean // Enable swipe-to-reply; default false
440
+ direction?: 'left' | 'right' // Swipe direction; default 'left'
441
+ onSwipe?: (message: TMessage) => void // Callback when swiped
442
+ renderAction?: ( // Custom swipe action component
443
+ progress: SharedValue<number>,
444
+ translation: SharedValue<number>,
445
+ position: 'left' | 'right'
446
+ ) => React.ReactNode
447
+ actionContainerStyle?: StyleProp<ViewStyle>
448
+ }
449
+
450
+ // Reply preview styling (above input toolbar)
451
+ previewStyle?: {
452
+ containerStyle?: StyleProp<ViewStyle>
453
+ textStyle?: StyleProp<TextStyle>
454
+ imageStyle?: StyleProp<ImageStyle>
455
+ }
456
+
457
+ // In-bubble reply styling
458
+ messageStyle?: {
459
+ containerStyle?: StyleProp<ViewStyle>
460
+ containerStyleLeft?: StyleProp<ViewStyle>
461
+ containerStyleRight?: StyleProp<ViewStyle>
462
+ textStyle?: StyleProp<TextStyle>
463
+ textStyleLeft?: StyleProp<TextStyle>
464
+ textStyleRight?: StyleProp<TextStyle>
465
+ imageStyle?: StyleProp<ImageStyle>
466
+ }
467
+
468
+ // Callbacks and state
469
+ message?: ReplyMessage // Controlled reply state
470
+ onClear?: () => void // Called when reply cleared
471
+ onPress?: (message: TMessage) => void // Called when reply preview tapped
472
+
473
+ // Custom renderers
474
+ renderPreview?: (props: ReplyPreviewProps) => React.ReactNode
475
+ renderMessageReply?: (props: MessageReplyProps) => React.ReactNode
476
+ }
477
+ ```
478
+
479
+ #### ReplyMessage Structure
480
+
481
+ When a message has a reply, it includes a `replyMessage` property:
482
+
483
+ ```typescript
484
+ interface ReplyMessage {
485
+ _id: string | number
486
+ text: string
487
+ user: User
488
+ image?: string
489
+ audio?: string
490
+ }
491
+ ```
492
+
493
+ #### Advanced Example with External State
494
+
495
+ ```tsx
496
+ const [replyMessage, setReplyMessage] = useState<ReplyMessage | null>(null)
497
+
498
+ <GiftedChat
499
+ messages={messages}
500
+ onSend={messages => {
501
+ const newMessages = messages.map(msg => ({
502
+ ...msg,
503
+ replyMessage: replyMessage || undefined,
504
+ }))
505
+ setMessages(prev => GiftedChat.append(prev, newMessages))
506
+ setReplyMessage(null)
507
+ }}
508
+ user={{ _id: 1 }}
509
+ reply={{
510
+ swipe: {
511
+ isEnabled: true,
512
+ direction: 'right',
513
+ onSwipe: setReplyMessage,
514
+ },
515
+ message: replyMessage,
516
+ onClear: () => setReplyMessage(null),
517
+ onPress: (msg) => scrollToMessage(msg._id),
518
+ }}
519
+ />
520
+ ```
521
+
522
+ #### Smooth Animations
523
+
524
+ The reply preview automatically animates when:
525
+ - **Appearing**: Smoothly expands from zero height with fade-in effect
526
+ - **Disappearing**: Smoothly collapses with fade-out effect
527
+ - **Content changes**: Smoothly transitions when replying to a different message
528
+
529
+ These animations use `react-native-reanimated` for 60fps performance.
530
+
397
531
  ### Scroll to Bottom
398
532
 
399
533
  - **`isScrollToBottomEnabled`** _(Bool)_ - Enables the scroll to bottom Component (Default is false)
400
534
  - **`scrollToBottomComponent`** _(Function)_ - Custom Scroll To Bottom Component container
401
535
  - **`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
536
+ - **`scrollToBottomStyle`** _(Object)_ - Custom style for Scroll To Bottom wrapper (position, bottom, right, etc.)
537
+ - **`scrollToBottomContentStyle`** _(Object)_ - Custom style for Scroll To Bottom content (size, background, shadow, etc.)
403
538
 
404
- ## Notes for Android
539
+ ### Maintaining Scroll Position (AI Chatbots)
405
540
 
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.
541
+ 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
542
 
408
- - Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`:
543
+ ```tsx
544
+ // Basic usage - always maintain scroll position
545
+ <GiftedChat
546
+ listProps={{
547
+ maintainVisibleContentPosition: {
548
+ minIndexForVisible: 0,
549
+ },
550
+ }}
551
+ />
552
+
553
+ // With auto-scroll threshold - auto-scroll if within 10 pixels of newest content
554
+ <GiftedChat
555
+ listProps={{
556
+ maintainVisibleContentPosition: {
557
+ minIndexForVisible: 0,
558
+ autoscrollToTopThreshold: 10,
559
+ },
560
+ }}
561
+ />
562
+
563
+ // Conditionally enable based on scroll state (recommended for chatbots)
564
+ const [isScrolledUp, setIsScrolledUp] = useState(false)
565
+
566
+ <GiftedChat
567
+ listProps={{
568
+ onScroll: (event) => {
569
+ setIsScrolledUp(event.contentOffset.y > 50)
570
+ },
571
+ maintainVisibleContentPosition: isScrolledUp
572
+ ? { minIndexForVisible: 0, autoscrollToTopThreshold: 10 }
573
+ : undefined,
574
+ }}
575
+ />
576
+ ```
577
+
578
+ ---
579
+
580
+ ## 📱 Platform Notes
581
+
582
+ ### Android
409
583
 
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
- ```
584
+ <details>
585
+ <summary><strong>Keyboard configuration</strong></summary>
417
586
 
418
- - For **Expo**, there are at least 2 solutions to fix it:
587
+ If you are using Create React Native App / Expo, no Android specific installation steps are required. Otherwise, we recommend modifying your project configuration:
419
588
 
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.:
589
+ Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`:
421
590
 
591
+ ```xml
592
+ <activity
593
+ android:name=".MainActivity"
594
+ android:label="@string/app_name"
595
+ android:windowSoftInputMode="adjustResize"
596
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
422
597
  ```
598
+
599
+ For **Expo**, you can append `KeyboardAvoidingView` after GiftedChat (Android only):
600
+
601
+ ```jsx
423
602
  <View style={{ flex: 1 }}>
424
603
  <GiftedChat />
425
- {
426
- Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />
427
- }
604
+ {Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />}
428
605
  </View>
429
606
  ```
430
607
 
431
- ## Notes for local development
608
+ </details>
432
609
 
433
- #### With create-react-app
610
+ ### Web (react-native-web)
434
611
 
435
- 1. `yarn add -D react-app-rewired`
436
- 2. `touch config-overrides.js`
612
+ <details>
613
+ <summary><strong>With create-react-app</strong></summary>
614
+
615
+ 1. Install react-app-rewired: `yarn add -D react-app-rewired`
616
+ 2. Create `config-overrides.js`:
437
617
 
438
618
  ```js
439
619
  module.exports = function override(config, env) {
@@ -453,23 +633,30 @@ module.exports = function override(config, env) {
453
633
  },
454
634
  },
455
635
  })
456
-
457
636
  return config
458
637
  }
459
638
  ```
460
639
 
461
- > You will find an example and a **web demo** here: [xcarpentier/gifted-chat-web-demo](https://github.com/xcarpentier/gifted-chat-web-demo)
640
+ > **Examples:**
641
+ > - [xcarpentier/gifted-chat-web-demo](https://github.com/xcarpentier/gifted-chat-web-demo)
642
+ > - [Gatsby example](https://github.com/xcarpentier/clean-archi-boilerplate/tree/develop/apps/web)
462
643
 
463
- > Another example with **Gatsby** : [xcarpentier/clean-archi-boilerplate](https://github.com/xcarpentier/clean-archi-boilerplate/tree/develop/apps/web)
644
+ </details>
464
645
 
465
- ## Testing
466
- `TEST_ID` is exported as constants that can be used in your testing library of choice
646
+ ---
647
+
648
+ ## đŸ§Ē Testing
649
+
650
+ <details>
651
+ <summary><strong>Triggering layout events in tests</strong></summary>
467
652
 
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.
653
+ `TEST_ID` is exported as constants that can be used in your testing library of choice.
654
+
655
+ Gifted Chat uses `onLayout` to determine the height of the chat container. To trigger `onLayout` during your tests:
469
656
 
470
657
  ```typescript
471
- const WIDTH = 200; // or any number
472
- const HEIGHT = 2000; // or any number
658
+ const WIDTH = 200
659
+ const HEIGHT = 2000
473
660
 
474
661
  const loadingWrapper = getByTestId(TEST_ID.LOADING_WRAPPER)
475
662
  fireEvent(loadingWrapper, 'layout', {
@@ -482,37 +669,144 @@ fireEvent(loadingWrapper, 'layout', {
482
669
  })
483
670
  ```
484
671
 
485
- ## Questions
672
+ </details>
673
+
674
+ ---
675
+
676
+ ## đŸ“Ļ Example App
677
+
678
+ The repository includes a comprehensive example app demonstrating all features:
679
+
680
+ ```bash
681
+ # Clone and install
682
+ git clone https://github.com/FaridSafi/react-native-gifted-chat.git
683
+ cd react-native-gifted-chat/example
684
+ yarn install
486
685
 
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)
686
+ # Run on iOS
687
+ npx expo run:ios
496
688
 
497
- ## You have a question?
689
+ # Run on Android
690
+ npx expo run:android
691
+
692
+ # Run on Web
693
+ npx expo start --web
694
+ ```
695
+
696
+ The example app showcases:
697
+ - đŸ’Ŧ Basic chat functionality
698
+ - 🎨 Custom message bubbles and avatars
699
+ - â†Šī¸ Reply to messages with swipe gesture
700
+ - ⚡ Quick replies (bot-style)
701
+ - âœī¸ Typing indicators
702
+ - 📎 Attachment actions
703
+ - 🔗 Link parsing and custom matchers
704
+ - 🌐 Web compatibility
705
+
706
+ ---
498
707
 
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
708
+ ## ❓ Troubleshooting
503
709
 
504
- ## Hire an expert
710
+ <details>
711
+ <summary><strong>TextInput is hidden on Android</strong></summary>
505
712
 
506
- Looking for a React Native freelance expert with more than 14 years of experience? Contact Xavier from his [website](https://xaviercarpentier.com)
713
+ Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`. See [Android configuration](#android) above.
507
714
 
508
- ## Author
715
+ </details>
509
716
 
510
- Feel free to ask me questions on Twitter [@FaridSafi](https://www.x.com/FaridSafi) or [@xcapetir](https://www.x.com/xcapetir)
717
+ <details>
718
+ <summary><strong>How to set Bubble color for each user?</strong></summary>
511
719
 
512
- ## Maintainer
720
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/672) for examples.
513
721
 
514
- Have any questions? Reach out to [Kesha Antonov](https://github.com/kesha-antonov)
722
+ </details>
515
723
 
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.
724
+ <details>
725
+ <summary><strong>How to customize InputToolbar styles?</strong></summary>
517
726
 
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!
727
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/662) for examples.
728
+
729
+ </details>
730
+
731
+ <details>
732
+ <summary><strong>How to manually dismiss the keyboard?</strong></summary>
733
+
734
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/647) for examples.
735
+
736
+ </details>
737
+
738
+ <details>
739
+ <summary><strong>How to use renderLoading?</strong></summary>
740
+
741
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/298) for examples.
742
+
743
+ </details>
744
+
745
+ ---
746
+
747
+ ## 🤔 Have a Question?
748
+
749
+ 1. Check this README first
750
+ 2. Search [existing issues](https://github.com/FaridSafi/react-native-gifted-chat/issues)
751
+ 3. Ask on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native-gifted-chat)
752
+ 4. Open a new issue if needed
753
+
754
+ ---
755
+
756
+ ## 🤝 Contributing
757
+
758
+ Contributions are welcome! Please feel free to submit a Pull Request.
759
+
760
+ 1. Fork the repository
761
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
762
+ 3. Install dependencies (`yarn install`)
763
+ 4. Make your changes
764
+ 5. Run tests (`yarn test`)
765
+ 6. Run linting (`yarn lint`)
766
+ 7. Build the library (`yarn build`)
767
+ 8. Commit your changes (`git commit -m 'Add amazing feature'`)
768
+ 9. Push to the branch (`git push origin feature/amazing-feature`)
769
+ 10. Open a Pull Request
770
+
771
+ ### Development Setup
772
+
773
+ ```bash
774
+ # Install dependencies
775
+ yarn install
776
+
777
+ # Build the library
778
+ yarn build
779
+
780
+ # Run tests
781
+ yarn test
782
+
783
+ # Run linting
784
+ yarn lint
785
+
786
+ # Full validation
787
+ yarn prepublishOnly
788
+ ```
789
+
790
+ ---
791
+
792
+ ## đŸ‘Ĩ Authors
793
+
794
+ **Original Author:** [Farid Safi](https://www.x.com/FaridSafi)
795
+
796
+ **Co-maintainer:** [Xavier Carpentier](https://www.x.com/xcapetir) - [Hire Xavier](https://xaviercarpentier.com)
797
+
798
+ **Maintainer:** [Kesha Antonov](https://github.com/kesha-antonov)
799
+
800
+ > 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).
801
+
802
+ ---
803
+
804
+ ## 📄 License
805
+
806
+ [MIT](LICENSE)
807
+
808
+ ---
809
+
810
+ <p align="center">
811
+ <sub>Built with â¤ī¸ by the React Native community</sub>
812
+ </p>