callstack / callstack/react-native-bottom-tabs

tabBarMinimizeBehavior: 'onScrollDown' not working on iOS 26+ with nested Stack Navigator

Open
#496 3 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
1.5k
Forks
109
Avg merge
11h 44m
Merged PRs (30d)
8

Description

### Before submitting a new issue

- [x] I tested using the latest version of the library, as the bug might be already fixed.
- [x] I tested using a [supported version](https://github.com/reactwg/react-native-releases/blob/main/docs/support.md) of react native.
- [x] I checked for possible duplicate issues, with possible answers.

### Bug summary

### Description
The `tabBarMinimizeBehavior: 'onScrollDown'` option is not working when using `createNativeBottomTabNavigator` with nested `NativeStackNavigator` screens on iOS 26+.

### Environment
- **React Native version:** 0.82.1
- **@react-navigation/bottom-tabs version:** 7.9.0
- **react-native-screens version:** 4.18.0
- **iOS version:** 26.0+
- **Platform:** iOS (iPhone)

### Steps to Reproduce
1. Create a `NativeBottomTabNavigator` with `tabBarMinimizeBehavior: 'onScrollDown'` and `tabBarControllerMode: 'tabSidebar'`
2. Use nested `NativeStackNavigator` as screen components (e.g., `HomeStack` containing `HomeScreen`)
3. Inside the nested screen, use a `ScrollView` with `contentInsetAdjustmentBehavior="automatic"`
4. Scroll down in the ScrollView
5. Tab bar does not minimize

### Expected Behavior
When scrolling down, the tab bar should minimize (collapse to show only the active tab on the left side) as per iOS 26's native behavior.

### Actual Behavior
The tab bar remains fully visible and does not minimize when scrolling down.

### Code Example

// TabStack.tsx
const NativeTab = createNativeBottomTabNavigator();

export const TabStack = () => {
const [isIOS26Plus, setIsIOS26Plus] = useState(false);

useEffect(() => {
if (Platform.OS === 'ios') {
const iosVersion = parseFloat(DeviceInfo.getSystemVersion());
setIsIOS26Plus(iosVersion >= 26.0);
}
}, []);

return (
({
lazy: false,
headerShown: false,
...(isIOS26Plus && {
tabBarMinimizeBehavior: 'onScrollDown',
tabBarControllerMode: 'tabSidebar',
}),
})}
>


);
};
// HomeStack.tsx
const Stack = createNativeStackNavigator();

export const HomeStack = () => {
return (



);
};
// HomeView.tsx (inside HomeScreen)

{/* Scrollable content */}
### Additional Context
- The issue occurs specifically with nested navigators (NativeTab → NativeStack → Screen)
- Works correctly when using direct screen components without nesting
- `contentInsetAdjustmentBehavior="automatic"` is set on the ScrollView as per documentation
- `tabBarControllerMode: 'tabSidebar'` is also set
- Tested on iOS 26.0+ devices/simulators

### Possible Related Issues
- The scroll detection might not be propagating correctly through nested navigators
- NativeTab might need direct access to the ScrollView to detect scroll events

### Library version

7.9.0

### Environment info

```shell
info Fetching system and libraries information...
System:
OS: macOS 26.2
CPU: (12) arm64 Apple M3 Pro
Memory: 205.39 MB / 36.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 22.9.0
path: /Users/emirbayir/.nvm/versions/node/v22.9.0/bin/node
Yarn:
version: 3.6.4
path: /opt/homebrew/bin/yarn
npm:
version: 11.6.2
path: /Users/emirbayir/.nvm/versions/node/v22.9.0/bin/npm
Watchman:
version: 2025.10.06.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.15.2
path: /Users/emirbayir/.rvm/gems/ruby-3.2.0/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.2
- iOS 26.2
- macOS 26.2
- tvOS 26.2
- visionOS 26.2
- watchOS 26.2
Android SDK:
API Levels:
- "33"
- "34"
- "35"
- "36"
Build Tools:
- 30.0.3
- 33.0.0
- 33.0.1
- 34.0.0
- 35.0.0
- 36.0.0
- 36.1.0
System Images:
- android-30 | Google APIs ARM 64 v8a
- android-35 | Google Play ARM 64 v8a
- android-35 | Pre-Release 16 KB Page Size Google Play ARM 64 v8a
- android-36 | Google Play ARM 64 v8a
- android-VanillaIceCream | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2025.1 AI-251.26094.121.2513.14007798
Xcode:
version: 26.2/17C52
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.16
path: /usr/bin/javac
Ruby:
version: 3.2.0
path: /Users/emirbayir/.rvm/rubies/ruby-3.2.0/bin/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.0.0
wanted: 20.0.0
react:
installed: 19.1.1
wanted: 19.1.1
react-native:
installed: 0.82.1
wanted: ^0.82.1
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: true

info React Native v0.83.0 is now available (your project is running on v0.82.1).
info Changelog: https://github.com/facebook/react-native/releases/tag/v0.83.0
info Diff: https://react-native-community.github.io/upgrade-helper/?from=0.82.1&to=0.83.0
info For more info, check out "https://reactnative.dev/docs/upgrading?os=macos".
```

### Steps to reproduce

1. …
2. …

### Reproducible sample code

```js
### Steps to Reproduce

1. **Create a new React Native project:**

npx react-native@0.82.1 init TestNativeTabMinimize
cd TestNativeTabMinimize
2. **Install required dependencies:**ash
npm install @react-navigation/bottom-tabs@7.9.0 @react-navigation/native@7.1.18 @react-navigation/native-stack@7.5.0 react-native-screens@4.18.0 react-native-safe-area-context@5.6.2 react-native-device-info@14.1.1
3. **For iOS, install pods:**

cd ios && pod install && cd ..
4. **Create the following files:**

**App.tsx:**

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { TabStack } from './src/navigation/TabStack';

export default function App() {
return (



);
}
**src/navigation/TabStack.tsx:**
import React, { useEffect, useState } from 'react';
import { createNativeBottomTabNavigator } from '@react-navigation/bottom-tabs/unstable';
import { Platform } from 'react-native';
import DeviceInfo from 'react-native-device-info';
import { HomeStack } from './HomeStack';
import { ProfileStack } from './ProfileStack';

const NativeTab = createNativeBottomTabNavigator();

export const TabStack = () => {
const [isIOS26Plus, setIsIOS26Plus] = useState(false);

useEffect(() => {
if (Platform.OS === 'ios') {
const iosVersion = parseFloat(DeviceInfo.getSystemVersion());
setIsIOS26Plus(iosVersion >= 26.0);
}
}, []);

return (
({
headerShown: false,
...(isIOS26Plus && {
tabBarMinimizeBehavior: 'onScrollDown',
tabBarControllerMode: 'tabSidebar',
}),
})}
>



);
};
**src/navigation/HomeStack.tsx:**

import React from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { HomeScreen } from '../screens/HomeScreen';

const Stack = createNativeStackNavigator();

export const HomeStack = () => {
return (



);
};
**src/navigation/ProfileStack.tsx:**

import React from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { ProfileScreen } from '../screens/ProfileScreen';

const Stack = createNativeStackNavigator();

export const ProfileStack = () => {
return (



);
};
**src/screens/HomeScreen.tsx:**sx
import React from 'react';
import { View, ScrollView, Text, StyleSheet, Platform } from 'react-native';
import DeviceInfo from 'react-native-device-info';

export const HomeScreen = () => {
const isIOS26Plus = Platform.OS === 'ios' && parseFloat(DeviceInfo.getSystemVersion()) >= 26.0;

return (


{Array.from({ length: 50 }, (_, i) => (

Item {i + 1}

))}


);
};

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
scrollView: {
flex: 1,
},
contentContainer: {
padding: 20,
paddingBottom: 100,
},
item: {
padding: 20,
marginBottom: 10,
backgroundColor: '#f0f0f0',
borderRadius: 8,
},
text: {
fontSize: 16,
},
});
**src/screens/ProfileScreen.tsx:**
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

export const ProfileScreen = () => {
return (

Profile Screen

);
};

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
text: {
fontSize: 24,
},
});
5. **Update index.js:**
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);
6. **Run the app:**
# iOS
npx react-native run-ios

# Or specify iOS 26+ simulator if available
npx react-native run-ios --simulator="iPhone 16 Pro (iOS 26.0)"
7. **Test the behavior:**
- Navigate to the "Home" tab
- Scroll down in the ScrollView
- **Expected:** Tab bar should minimize (collapse to show only active tab on left)
- **Actual:** Tab bar remains fully visible

### Platform
- **iOS:** ✅ Issue occurs
- **Android:** ❌ Not applicable (feature is iOS 26+ only)

### Test Environment
- **Simulator:** iPhone 16 Pro (iOS 26.0) or any iOS 26+ simulator
- **Physical Device:** Any iPhone running iOS 26.0 or later
- **React Native:** 0.82.1
- **@react-navigation/bottom-tabs:** 7.9.0
- **react-native-screens:** 4.18.0

### Additional Notes
- The issue only occurs when using **nested navigators** (NativeTab → NativeStack → Screen)
- If you use direct screen components without nesting, the minimize behavior works correctly
- The `contentInsetAdjustmentBehavior="automatic"` is set on the ScrollView as per documentation requirements
- `tabBarControllerMode: 'tabSidebar'` is also configured

### Minimal Reproduction Repository
[Link to GitHub repository with minimal reproduction code - if you create one]
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.