Before submitting a new issue
Bug summary
Top Navigation/Toolbar appears on iPad with iPadOS 26+ even with headerShown: false and custom bottom tab bar configured. This worked correctly on iPadOS 18.5, but broke on iPadOS 26.
Expected behavior
Only the custom bottom tab bar should be visible. No top navigation toolbar should appear (as it did on iPadOS 18.5).
Actual behavior
On iPad with iPadOS 26+, a new top navigation/toolbar appears despite:
- Setting
headerShown: false
- Using custom bottom tab bar with
tabBarStyle={{ display: "none" }}
- Custom tab bar positioned at bottom
On iPadOS 18.5, this setup worked perfectly without the top toolbar.
This appears to be a breaking change in the iPadOS 26 iPad UI pattern with a new segmented control.
Question about PR #420 and iPadOS 26 compatibility
I'm using the latest @bottom-tabs/monorepo from GitHub (main branch) which includes the changes from PR #420. However, the top toolbar still appears on iPadOS 26.
PR #420 moves .hideTabBar(props.tabBarHidden) INSIDE each Tab's child view:
Tab(value: tabData.key, role: tabData.role?.convert()) {
child
.ignoresSafeArea(.container, edges: .all)
.tabAppear(using: context)
.hideTabBar(props.tabBarHidden) // Moved here in PR #420
} label: {
TabItem(title: tabData.title, icon: icon, sfSymbol: tabData.sfSymbol, labeled: props.labeled)
}
Is PR #420 sufficient for iPadOS 26, or do we need an additional fix like .toolbar(.hidden, for: .tabBar) for iPadOS 26+ compatibility?
I tested adding .toolbar(.hidden, for: .tabBar) after .hideTabBar() and it seems to hide the toolbar, but I want to confirm if this is the correct approach or if there's a better solution.
Library version
Environment info
- react-native: 0.81.4
- expo: ~54.0.13
- iPadOS: 18.5 (works) → 26.0+ (broken - iPad Simulator)
- Platform: iPadOS
- Device: iPad Simulator
Steps to reproduce
- Create app with @bottom-tabs/react-navigation on Expo Router
- Test on iPad with iPadOS 18.5 → Works
- Test on iPad with iPadOS 26+ → Top toolbar appears
- Expected: Toolbar should not appear on iPadOS 26 either
Reproducible sample code
# app/(tabs)/\_layout.tsx
import { withLayoutContext } from "expo-router";
import { createNativeBottomTabNavigator } from "@bottom-tabs/react-navigation";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Platform, View, Pressable, StyleSheet, Image, Dimensions } from "react-native";
const BottomTabNavigator = createNativeBottomTabNavigator().Navigator;
const Tabs = withLayoutContext(BottomTabNavigator);
function CustomBottomTabBar({ state, descriptors, navigation }: any) {
const insets = useSafeAreaInsets();
return (
<View style={[styles.tabBar, { paddingBottom: Math.max(insets.bottom, 8) }]}>
{state.routes.map((route: any, index: number) => {
const { options } = descriptors[route.key];
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: "tabPress",
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name, route.params);
}
};
const iconSource = options.tabBarIcon
? options.tabBarIcon({
focused: isFocused,
color: isFocused ? "#007AFF" : "#999999",
size: 24,
})
: null;
return (
<Pressable
key={route.key}
onPress={onPress}
style={[styles.tabItem, isFocused && styles.tabItemActive]}
>
{iconSource && (
<Image
source={iconSource}
style={{ width: 24, height: 24 }}
resizeMode="contain"
/>
)}
</Pressable>
);
})}
</View>
);
}
const styles = StyleSheet.create({
tabBar: {
position: "absolute",
left: 0,
right: 0,
bottom: 0,
flexDirection: "row",
backgroundColor: "#fff",
borderTopWidth: 1,
borderTopColor: "#e5e5e5",
height: 60,
},
tabItem: {
flex: 1,
justifyContent: "center",
alignItems: "center",
paddingVertical: 8,
},
tabItemActive: {
borderTopWidth: 2,
borderTopColor: "#007AFF",
},
});
export default function TabLayout() {
const isIPad = Platform.OS === "ios" && Dimensions.get("window").width >= 768;
return (
<Tabs
screenOptions={{
headerShown: false,
sceneStyle: { paddingBottom: isIPad ? 68 : 0 },
}}
tabBar={isIPad ? (props) => <CustomBottomTabBar {...props} /> : undefined}
tabBarStyle={isIPad ? { display: "none" } : undefined}
>
<Tabs.Screen
name="discover"
options={{
title: "Entdecken",
tabBarIcon: ({ focused }) => (focused ? icons.compass : icons.compassOutline),
}}
/>
<Tabs.Screen
name="browse"
options={{
title: "Stöbern",
tabBarIcon: ({ focused }) => (focused ? icons.search : icons.searchOutline),
}}
/>
<Tabs.Screen
name="add"
options={{
title: "Hinzufügen",
tabBarIcon: ({ focused }) => (focused ? icons.addCircle : icons.addCircleOutline),
}}
/>
<Tabs.Screen
name="reports"
options={{
title: "Meldungen",
tabBarIcon: ({ focused }) => (focused ? icons.flag : icons.flagOutline),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: "Profil",
tabBarIcon: ({ focused }) => (focused ? icons.person : icons.personOutline),
}}
/>
</Tabs>
);
}
Before submitting a new issue
Bug summary
Top Navigation/Toolbar appears on iPad with iPadOS 26+ even with
headerShown: falseand custom bottom tab bar configured. This worked correctly on iPadOS 18.5, but broke on iPadOS 26.Expected behavior
Only the custom bottom tab bar should be visible. No top navigation toolbar should appear (as it did on iPadOS 18.5).
Actual behavior
On iPad with iPadOS 26+, a new top navigation/toolbar appears despite:
headerShown: falsetabBarStyle={{ display: "none" }}On iPadOS 18.5, this setup worked perfectly without the top toolbar.
This appears to be a breaking change in the iPadOS 26 iPad UI pattern with a new segmented control.
Question about PR #420 and iPadOS 26 compatibility
I'm using the latest
@bottom-tabs/monorepofrom GitHub (main branch) which includes the changes from PR #420. However, the top toolbar still appears on iPadOS 26.PR #420 moves
.hideTabBar(props.tabBarHidden)INSIDE each Tab's child view:Is PR #420 sufficient for iPadOS 26, or do we need an additional fix like
.toolbar(.hidden, for: .tabBar)for iPadOS 26+ compatibility?I tested adding
.toolbar(.hidden, for: .tabBar)after.hideTabBar()and it seems to hide the toolbar, but I want to confirm if this is the correct approach or if there's a better solution.Library version
Environment info
- react-native: 0.81.4 - expo: ~54.0.13 - iPadOS: 18.5 (works) → 26.0+ (broken - iPad Simulator) - Platform: iPadOS - Device: iPad SimulatorSteps to reproduce
Reproducible sample code