callstack / callstack/react-native-bottom-tabs

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

Ouverte
#496 3 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
bug
Langage dominant
TypeScript
Étoiles
1.5k
Forks
109
Merge moyen
11 h 44 min
PR mergées (30 j)
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]
```

Guide de contribution

Ouvrir le guide de contribution

Piste de recherche

Commencez par les fichiers de reproduction src/navigation/TabStack.tsx, src/navigation/HomeStack.tsx et src/screens/HomeScreen.tsx, puis exécutez l’exemple sur un simulateur iOS 26 ou version ultérieure. Comparez la configuration du navigateur imbriqué avec le comportement signalé pour un écran direct et suivez la manière dont le ScrollView est connecté au contrôleur de la barre d’onglets inférieure. C’est terminé lorsque la barre d’onglets se réduit lors du défilement vers le bas dans l’écran imbriqué.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
ios, react-native, typescript
Domaine
mobile
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.