Skip to content

Instantly share code, notes, and snippets.

@pugson
Created March 24, 2026 01:00
Show Gist options
  • Select an option

  • Save pugson/0ea6124c2590984793a8a6afbfcaa1f4 to your computer and use it in GitHub Desktop.

Select an option

Save pugson/0ea6124c2590984793a8a6afbfcaa1f4 to your computer and use it in GitHub Desktop.
react-native-bottom-tabs Liquid Glass minimizeBehavior with LegendList, FlashList, etc.
demo.mp4

iOS 26 Liquid Glass Tab Bar Minimize on Scroll in React Native

Liquid Glass tab bars can minimize into a compact floating pill when you scroll. SwiftUI makes this easy with .tabBarMinimizeBehavior(.onScrollDown) but if you're using React Native with react-native-bottom-tabs, it doesn't work virtualized list libraries like LegendList or FlashList. Here is a simple patch to get it working.

Usage

Apply the patch with your package manager (bun, pnpm, yarn, etc.) and make a new native build, then pass minimizeBehavior to your tab navigator:

<Tabs minimizeBehavior="onScrollDown">
  <Tabs.Screen name="home" />
  <Tabs.Screen name="settings" />
</Tabs>

Options: "automatic", "onScrollDown", "onScrollUp", "never".

Works with ScrollView, FlatList, SectionList, FlashList, LegendList, or any component backed by UIScrollView.

diff --git a/ios/RepresentableView.swift b/ios/RepresentableView.swift
index 09adaca401c716dd6c47590ffc7fe5646de2e50b..ff10f3977845832a3f955c1e8d93ef61a034c3b1 100644
--- a/ios/RepresentableView.swift
+++ b/ios/RepresentableView.swift
@@ -30,3 +30,56 @@ struct RepresentableView: PlatformViewRepresentable {
#endif
}
+
+#if !os(macOS)
+extension UIView {
+ /// BFS search for the first UIScrollView descendant
+ func findDescendantScrollView() -> UIScrollView? {
+ var queue: [UIView] = subviews.reversed()
+ while !queue.isEmpty {
+ let view = queue.removeLast()
+ if let scrollView = view as? UIScrollView {
+ return scrollView
+ }
+ queue.insert(contentsOf: view.subviews, at: 0)
+ }
+ return nil
+ }
+}
+
+/// Swizzles UIViewController.contentScrollView(for:) so UIKit can discover
+/// React Native UIScrollView descendants for tab bar minimize behavior.
+@available(iOS 15.0, *)
+enum ScrollViewBridging {
+ private static var installed = false
+
+ static func install() {
+ guard !installed else { return }
+ installed = true
+
+ let original = class_getInstanceMethod(
+ UIViewController.self,
+ #selector(UIViewController.contentScrollView(for:))
+ )
+ let swizzled = class_getInstanceMethod(
+ UIViewController.self,
+ #selector(UIViewController.rntabs_contentScrollView(for:))
+ )
+ if let original, let swizzled {
+ method_exchangeImplementations(original, swizzled)
+ }
+ }
+}
+
+@available(iOS 15.0, *)
+extension UIViewController {
+ @objc func rntabs_contentScrollView(for edge: NSDirectionalRectEdge) -> UIScrollView? {
+ // Call original (swizzled) implementation first
+ if let original = rntabs_contentScrollView(for: edge) {
+ return original
+ }
+ // Fall back to searching the view hierarchy for a RN scroll view
+ return view.findDescendantScrollView()
+ }
+}
+#endif
diff --git a/ios/TabViewImpl.swift b/ios/TabViewImpl.swift
index 72938be90540ea3a483d7db9a80fb74c04d31272..376756df1185fed074ac2db5539e93050e24cf95 100644
--- a/ios/TabViewImpl.swift
+++ b/ios/TabViewImpl.swift
@@ -64,6 +64,10 @@ struct TabViewImpl: View {
#if !os(macOS)
tabController.view.backgroundColor = .clear
tabController.viewControllers?.forEach { $0.view.backgroundColor = .clear }
+ // Swizzle contentScrollView(for:) so UIKit can find RN scroll views for tab bar minimize
+ if #available(iOS 15.0, *) {
+ ScrollViewBridging.install()
+ }
#endif
#if os(macOS)
tabBar = tabController
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment