Skip to content

feat: introduce KeyboardChatScrollView#1314

Merged
kirillzyusko merged 102 commits intomainfrom
feat/chat-kit
Feb 24, 2026
Merged

feat: introduce KeyboardChatScrollView#1314
kirillzyusko merged 102 commits intomainfrom
feat/chat-kit

Conversation

@kirillzyusko
Copy link
Copy Markdown
Owner

@kirillzyusko kirillzyusko commented Feb 18, 2026

📜 Description

Added KeyboardChatScrollView component for building chat apps easy than before 😊

💡 Motivation and Context

It's possible to build chat app with this library (keyboard handling), but:

  • you can not use generic components like KeyboardAvoidingView that will work well everywhere;
  • you can write custom code, but eventually it's a lot of code and you need to understand internals of RN/this library to deliver best possible experience.

But in fact all chat app keyboard handling is similar to each other:

  • we want to push the content when keyboard appears (or in certain case we don't want it, it's customizable)
  • we want to have interactive keyboard dismissal;
  • we want to freeze position of the chat when keyboard disappears to show custom "input" element (i. e. emoji picker, bottom sheet);
  • we want to use it with virtualized lists;
  • we want to see 120FPS animation during keyboard opening/dismissal;
  • we want to extend keyboard space (keyboard padding);
  • we want to have custom offset if chat is not attached to the bottom of the screen).

And for building chat app that will satisfy these requirements you'll need to write many lines of code, for example: Expensify/App#71440 and Expensify/App#71438. The purpose of this PR is to expose a component that will be easy to integrate in client apps. Similar to what we did with KeyboardAvoidingView, KeyboardAwareScrollView and other components

The key idea in this component is that we don't change layout of ScrollView and instead extend scrollable area. In this case it's super-performant and allows to introduce advanced features with keyboard, such as conditional content re-positioning (composer is built on top of KeyboardStickyView, and this is the layout that is used in many chat apps, such as Telegram, ChatGPT, etc.). On iOS it's achieved using contentInsets. On Android - ClippingScrollViewDecorator helps a lot.

All logic with content re-positioning is placed in hook file and covered by unit tests. Later I'm planning to cover this component with e2e tests (and fix minor styling issues)

Important

Interactive keyboard dismissal may not work really well yet. Turns out Android+Fabric has some issues (but paper may have it too). iOS 26 in general is super buggy. But I'm happy to have a component-based public API where we can test interactive dismissal. Before it was kind of cool feature, but not really well tested. Now it will be built inside the public component, so we can properly fix it (same as we had onSelectionChange event - before it wasn't stable, but when we added it to KeyboardAwareScrollView it improved stability a lot).

Closes #1011 #594 #951 #871 #1110

📢 Changelog

Android

  • added support for contentInsetTop property for ClippingScrollViewDecorator;

JS

  • setup unit tests in main repo (with reanimated dependency);
  • write useChatKeyboard hooks that responsible for extending scroll range and content re-positioning.

Docs

  • added KeyboardChatScrollView API reference page;
  • added "Building chat app" guide;
  • added Expo snack into example so that people can experiment with API directly in browser;
  • added references between "Components overview" -> "Building chat app", "Building chat app" -> API reference.

🤔 How Has This Been Tested?

Tested manually on:

  • Pixel 7 Pro (API 36.1, real device)
  • Xiaomi Redmi Note 5 Pro (API 28, real device)
  • iPhone 17 Pro (iOS 26.2, simulator)
  • iPhone 16 Pro (iOS 26.3, real device)

📸 Screenshots (if appropriate):

React commits (keyboard opening)

KeyboardAvoidingView KeyboardChatScrollView
image image

Re-layout pass

KeyboardAvoidingView KeyboardChatScrollView
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-02-20.at.22.21.00.mp4
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-02-20.at.22.21.52.mp4

Non-inverted list

Android iOS
telegram-cloud-document-2-5247105741013160806.mp4
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-02-21.at.23.43.53.mov

Inverted list

Android iOS
telegram-cloud-document-2-5247105741013160807.mp4
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-02-21.at.23.44.59.mov

🐛 Tests conducted

  • resolve all todos
  • send message functionality
  • example with sticky footer
  • inverted support (via menu)
  • hold position when message added (if list is not inverted done by default - we perform scroll in effect)
  • one message, always mode, list just mounts - we miss layout/contentSize metrics, so content gets pushed up
  • don't scroll when only few messages visible
  • add freeze property
  • cover by unit tests
  • add offset property
  • FlashList/FlatList integration (Legend/FlashList were re-mounting view, need to pass stable reference)
  • optimized approach for iOS/Android (contentOffset on iOS without changes in every frame)
  • inverted support
  • fix FlatList/LegendList scrolling to the last message
  • inverted list, scroll to top, close keyboard - position must be unchanged
  • render first message from bottom from top (not only inverted prop!)
  • interactive dismissal
  • customizable behavior when to scroll (i. e. "always", "when bottom reached", "never")
  • make sure no re-layout happens on every frame (cover by e2e tests)
  • check 120 FPS on all platforms

📝 Checklist

  • CI successfully passed
  • I added new mocks and corresponding unit-tests if library API was changed

@kirillzyusko kirillzyusko self-assigned this Feb 18, 2026
@kirillzyusko kirillzyusko added documentation Improvements or additions to documentation enhancement New feature or request 🤖 android Android specific 🍎 iOS iOS specific 📚 components Anything related to the exported components of this library tests You added or changed unit tests KeyboardChatScrollView 💬 Anything about chat functionality labels Feb 18, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Images automagically compressed by Calibre's image-actions

Compression reduced images by 41%, saving 12.5 KB.

Filename Before After Improvement Visual comparison
FabricExample/src/screens/Examples/ChatKit/send.png 30.6 KB 18.0 KB 41.0% View diff

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 18, 2026

📊 Package size report

Current size Target Size Difference
279084 bytes 244052 bytes 35032 bytes 📈

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 18, 2026

PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-02-24 10:39 UTC

@argos-ci
Copy link
Copy Markdown

argos-ci Bot commented Feb 18, 2026

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ⚠️ Changes detected (Review) 1 changed Feb 24, 2026, 10:35 AM

@kirillzyusko kirillzyusko changed the title feat: chat kit feat: KeyboardChatScrollView Feb 20, 2026
@kirillzyusko kirillzyusko changed the title feat: KeyboardChatScrollView feat: introduce KeyboardChatScrollView Feb 20, 2026
Comment thread docs/docs/api/components/keyboard-chat-scroll-view.mdx Outdated
Comment thread FabricExample/src/screens/Examples/KeyboardChatScrollView/TODO.md Outdated
@kirillzyusko kirillzyusko mentioned this pull request Feb 23, 2026
2 tasks
@kirillzyusko kirillzyusko marked this pull request as ready for review February 24, 2026 10:29
@kirillzyusko kirillzyusko merged commit 11c0dbf into main Feb 24, 2026
27 checks passed
@kirillzyusko kirillzyusko deleted the feat/chat-kit branch February 24, 2026 10:36
@kirillzyusko kirillzyusko added the 🚨 requires API changes 🚨 Changes that requires changes in library API label Mar 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖 android Android specific 📚 components Anything related to the exported components of this library documentation Improvements or additions to documentation enhancement New feature or request 🍎 iOS iOS specific KeyboardChatScrollView 💬 Anything about chat functionality 🚨 requires API changes 🚨 Changes that requires changes in library API tests You added or changed unit tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant