Skip to content

Commit 89b6a5b

Browse files
authored
feat: implement iOS 26 minimize behavior (#367)
* feat: implement iOS 26 minimize behavior * feat: add docs
1 parent 110527c commit 89b6a5b

File tree

14 files changed

+108
-2
lines changed

14 files changed

+108
-2
lines changed

.changeset/ready-paths-train.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'react-native-bottom-tabs': patch
3+
---
4+
5+
feat: implement iOS 26 minimizeBehavior feature

apps/example/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ PODS:
11801180
- React-jsiexecutor
11811181
- React-RCTFBReactNativeSpec
11821182
- ReactCommon/turbomodule/core
1183-
- react-native-bottom-tabs (0.9.1):
1183+
- react-native-bottom-tabs (0.9.2):
11841184
- DoubleConversion
11851185
- glog
11861186
- RCT-Folly (= 2024.11.18.00)
@@ -1931,7 +1931,7 @@ SPEC CHECKSUMS:
19311931
React-logger: 1935d6e6461e9c8be4c87af56c56a4876021171e
19321932
React-Mapbuffer: 212171f037e3b22e6c2df839aa826806da480b85
19331933
React-microtasksnativemodule: a0ffd165c39251512d8cf51e9e8f5719dabc38b6
1934-
react-native-bottom-tabs: 7c7ee94435e518759b414e89068956096a1adec7
1934+
react-native-bottom-tabs: 6ee03990297f7e37f5c1dd6f5259cee851733d4f
19351935
react-native-safe-area-context: e54b360402f089600c2fb0d825d1d3d918b99e15
19361936
React-nativeconfig: cb207ebba7cafce30657c7ad9f1587a8f32e4564
19371937
React-NativeModulesApple: 76a5d35322908fbc88871e6dd20433bea2b8b2db

apps/example/src/Examples/SFSymbols.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export default function SFSymbols() {
4747
return (
4848
<TabView
4949
sidebarAdaptable
50+
minimizeBehavior="onScrollDown"
5051
navigationState={{ index, routes }}
5152
onIndexChange={setIndex}
5253
renderScene={renderScene}

docs/docs/docs/guides/standalone-usage.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export default function TabViewExample() {
4747
renderScene={renderScene}
4848
onIndexChange={setIndex}
4949
labeled
50+
minimizeBehavior="onScrollDown" // iOS 26+: Hide tab bar when scrolling down
5051
/>
5152
);
5253
}
@@ -143,6 +144,22 @@ Supported properties:
143144
Appearance attributes for the tab bar when a scroll view is at the bottom.
144145
- Type: `'default' | 'opaque' | 'transparent'`
145146

147+
#### `minimizeBehavior` <Badge text="iOS 26+" type="info" />
148+
149+
Controls how the tab bar behaves when content is scrolled.
150+
- Type: `'automatic' | 'onScrollDown' | 'onScrollUp' | 'never'`
151+
- Default: `undefined` (uses system default)
152+
153+
Options:
154+
- `automatic`: Platform determines the behavior
155+
- `onScrollDown`: Tab bar minimizes when scrolling down
156+
- `onScrollUp`: Tab bar minimizes when scrolling up
157+
- `never`: Tab bar never minimizes
158+
159+
:::note
160+
This feature requires iOS 26.0 or later and is only available on iOS. On older versions, this prop is ignored.
161+
:::
162+
146163
#### `tabBarActiveTintColor`
147164

148165
Color for the active tab.

docs/docs/docs/guides/usage-with-react-navigation.mdx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,23 @@ Tab views using the sidebar adaptable style have an appearance
158158

159159
Whether to enable haptic feedback on tab press. Defaults to false.
160160

161+
#### `minimizeBehavior` <Badge text="iOS 26+" type="info" />
162+
163+
Controls how the tab bar behaves when content is scrolled.
164+
165+
- Type: `'automatic' | 'onScrollDown' | 'onScrollUp' | 'never'`
166+
- Default: `undefined` (uses system default)
167+
168+
Options:
169+
- `automatic`: Platform determines the behavior
170+
- `onScrollDown`: Tab bar minimizes when scrolling down
171+
- `onScrollUp`: Tab bar minimizes when scrolling up
172+
- `never`: Tab bar never minimizes
173+
174+
:::note
175+
This feature requires iOS 26.0 or later and is only available on iOS. On older versions, this prop is ignored.
176+
:::
177+
161178
#### `tabLabelStyle`
162179

163180
Object containing styles for the tab label.

packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,7 @@ class RCTTabViewManager(context: ReactApplicationContext) :
163163

164164
override fun setScrollEdgeAppearance(view: ReactBottomNavigationView?, value: String?) {
165165
}
166+
167+
override fun setMinimizeBehavior(view: ReactBottomNavigationView?, value: String?) {
168+
}
166169
}

packages/react-native-bottom-tabs/android/src/oldarch/RCTTabViewManager.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ class RCTTabViewManager(context: ReactApplicationContext) : ViewGroupManager<Rea
137137
fun setSidebarAdaptable(view: ReactBottomNavigationView, flag: Boolean) {
138138
}
139139

140+
@ReactProp(name = "minimizeBehavior")
141+
fun setMinimizeBehavior(view: ReactBottomNavigationView, flag: Boolean) {
142+
}
143+
140144
@ReactProp(name = "hapticFeedbackEnabled")
141145
fun setHapticFeedbackEnabled(view: ReactBottomNavigationView, value: Boolean) {
142146
tabViewImpl.setHapticFeedbackEnabled(view, value)

packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewComponentView.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
130130
if (oldViewProps.sidebarAdaptable != newViewProps.sidebarAdaptable) {
131131
_tabViewProvider.sidebarAdaptable = newViewProps.sidebarAdaptable;
132132
}
133+
134+
if (oldViewProps.minimizeBehavior != newViewProps.minimizeBehavior) {
135+
_tabViewProvider.minimizeBehavior = RCTNSStringFromString(newViewProps.minimizeBehavior);
136+
}
133137

134138
if (oldViewProps.disablePageAnimations != newViewProps.disablePageAnimations) {
135139
_tabViewProvider.disablePageAnimations = newViewProps.disablePageAnimations;

packages/react-native-bottom-tabs/ios/RCTTabViewViewManager.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ @implementation RCTTabView
2929
RCT_EXPORT_VIEW_PROPERTY(onNativeLayout, RCTDirectEventBlock)
3030
RCT_EXPORT_VIEW_PROPERTY(selectedPage, NSString)
3131
RCT_EXPORT_VIEW_PROPERTY(tabViewStyle, NSString)
32+
RCT_EXPORT_VIEW_PROPERTY(minimizeBehavior, NSString)
3233
RCT_EXPORT_VIEW_PROPERTY(icons, NSArray<RCTImageSource *>);
3334
RCT_EXPORT_VIEW_PROPERTY(sidebarAdaptable, BOOL)
3435
RCT_EXPORT_VIEW_PROPERTY(labeled, BOOL)

packages/react-native-bottom-tabs/ios/TabViewImpl.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct TabViewImpl: View {
2828
onLayout(size)
2929
}
3030
}
31+
.tabBarMinimizeBehavior(props.minimizeBehavior)
3132
#if !os(tvOS) && !os(macOS) && !os(visionOS)
3233
.onTabItemEvent { index, isLongPress in
3334
let item = props.filteredItems[safe: index]
@@ -333,6 +334,23 @@ extension View {
333334
}
334335
}
335336

337+
@ViewBuilder
338+
func tabBarMinimizeBehavior(_ behavior: MinimizeBehavior?) -> some View {
339+
#if compiler(>=6.2)
340+
if #available(iOS 26.0, *) {
341+
if let behavior {
342+
self.tabBarMinimizeBehavior(behavior.convert())
343+
} else {
344+
self
345+
}
346+
} else {
347+
self
348+
}
349+
#else
350+
self
351+
#endif
352+
}
353+
336354
@ViewBuilder
337355
func hideTabBar(_ flag: Bool) -> some View {
338356
#if !os(macOS)

0 commit comments

Comments
 (0)