Skip to content

Commit 196d06e

Browse files
committed
feat: allow for custom JS tab bars
1 parent e99bb09 commit 196d06e

File tree

20 files changed

+181
-114
lines changed

20 files changed

+181
-114
lines changed

apps/example/app.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
"android": [
1717
"dist/res",
1818
"dist/main.android.jsbundle",
19-
"./node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"
19+
"../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"
2020
],
2121
"ios": [
2222
"dist/assets",
2323
"dist/main.ios.jsbundle",
24-
"./node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"
24+
"../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"
2525
],
2626
"macos": [
2727
"dist/assets",

apps/example/ios/Podfile.lock

Lines changed: 48 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,32 +1209,7 @@ PODS:
12091209
- ReactCommon/turbomodule/bridging
12101210
- ReactCommon/turbomodule/core
12111211
- Yoga
1212-
- react-native-bottom-tabs (0.7.3):
1213-
- DoubleConversion
1214-
- glog
1215-
- RCT-Folly (= 2024.01.01.00)
1216-
- RCTRequired
1217-
- RCTTypeSafety
1218-
- React-Core
1219-
- React-debug
1220-
- React-Fabric
1221-
- React-featureflags
1222-
- React-graphics
1223-
- React-ImageManager
1224-
- React-jsi
1225-
- react-native-bottom-tabs/common (= 0.7.3)
1226-
- React-NativeModulesApple
1227-
- React-RCTFabric
1228-
- React-rendererdebug
1229-
- React-utils
1230-
- ReactCodegen
1231-
- ReactCommon/turbomodule/bridging
1232-
- ReactCommon/turbomodule/core
1233-
- SDWebImage (>= 5.19.1)
1234-
- SDWebImageSVGCoder (>= 1.7.0)
1235-
- SwiftUIIntrospect (~> 1.0)
1236-
- Yoga
1237-
- react-native-bottom-tabs/common (0.7.3):
1212+
- react-native-bottom-tabs (0.8.3):
12381213
- DoubleConversion
12391214
- glog
12401215
- RCT-Folly (= 2024.01.01.00)
@@ -1914,68 +1889,68 @@ SPEC CHECKSUMS:
19141889
FBLazyVector: 430e10366de01d1e3d57374500b1b150fe482e6d
19151890
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
19161891
glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
1917-
RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740
1892+
RCT-Folly: 34124ae2e667a0e5f0ea378db071d27548124321
19181893
RCTDeprecation: 726d24248aeab6d7180dac71a936bbca6a994ed1
19191894
RCTRequired: a94e7febda6db0345d207e854323c37e3a31d93b
19201895
RCTTypeSafety: 28e24a6e44f5cbf912c66dde6ab7e07d1059a205
19211896
React: c2830fa483b0334bda284e46a8579ebbe0c5447e
19221897
React-callinvoker: 4aecde929540c26b841a4493f70ebf6016691eb8
1923-
React-Core: 1e3c04337857fa7fb7559f73f6f29a2a83a84b9c
1924-
React-CoreModules: 9fac2d31803c0ed03e4ddaa17f1481714f8633a5
1925-
React-cxxreact: c72a7a8066fc4323ea85a3137de50c8a10a69794
1898+
React-Core: 65374ea054f3f00eaa3c8bb5e989cb1ba8128844
1899+
React-CoreModules: f53e0674e1747fa41c83bc970e82add97b14ad87
1900+
React-cxxreact: bb77e88b645c5378ecd0c30c94f965a8294001d8
19261901
React-debug: 3d21f69d8def0656f8b8ec25c0f05954f4d862c5
1927-
React-defaultsnativemodule: 95882787871a9e80337f464e4643f1c5e0a39198
1928-
React-domnativemodule: dc8aac826a90479ca4e05f096f1f8cd35c216f31
1929-
React-Fabric: 9347fa5c8fbfac6d5276dd9e52c91058467d0960
1930-
React-FabricComponents: 68b9f8c4a7189c055a7eb67b182e8d98c4f75f47
1931-
React-FabricImage: 062e20f8b360ca008f44d00a639951c8c37ba2aa
1902+
React-defaultsnativemodule: 7af17cb26da34dc11b9f285d20d500a7e02f4f31
1903+
React-domnativemodule: c1068e2e275e192459690bd27d680cacf2396962
1904+
React-Fabric: 8c9cb59af7be7270b7ac5da739c260219bf2d36d
1905+
React-FabricComponents: 7c4879ad6944d75e4e3e2752e93b564fe361ab88
1906+
React-FabricImage: 19fabe4f6100ab7ea7a97641a9e36db72152cea4
19321907
React-featureflags: ee1abd6f71555604a36cda6476e3c502ca9a48e5
1933-
React-featureflagsnativemodule: 209f660bc398849cfb81712c93010276f25f337b
1934-
React-graphics: d7dd9c8d75cad5af19e19911fa370f78f2febd96
1935-
React-idlecallbacksnativemodule: 17a0e379a7e3c9bc9653b6902f22f4208658d687
1936-
React-ImageManager: ab7a7d17dd0ff1ef1d4e1e88197d1119da9957ce
1908+
React-featureflagsnativemodule: 22efd12eeeebb24c4259685763d8cb8fa8dfce32
1909+
React-graphics: f5c4cf3abc5aa083e28fe7a866bd95fb3bbbc1e0
1910+
React-idlecallbacksnativemodule: 1abfbc956bbf8164fee194c9fb730640b1b5b876
1911+
React-ImageManager: cb78d7a24f45f8f9a5a1640b52fce4c9f637f98d
19371912
React-jsc: 4d3352be620f3fe2272238298aaccc9323b01824
1938-
React-jserrorhandler: d9e867bb83b868472f3f7601883f0403b3e3942d
1939-
React-jsi: 490deef195fd3f01d57dc89dda8233a84bd54b83
1940-
React-jsiexecutor: 13bcb5e11822b2a6b69dbb175a24a39e24a02312
1941-
React-jsinspector: 5b93e72babcbfcbf84dd19576652c6b949d144af
1942-
React-jsitracing: 0e8c0aadb1fcec6b1e4f2a66ee3b0da80f0f8615
1943-
React-logger: d79b704bf215af194f5213a6b7deec50ba8e6a9b
1944-
React-Mapbuffer: b982d5bba94a8bc073bda48f0d27c9b28417fae3
1945-
React-microtasksnativemodule: 8fa285fed833a04a754bf575f8ded65fc240b88d
1946-
react-native-bottom-tabs: b6b3dc2e971c860a0a6d763701929d1899f666a0
1947-
react-native-safe-area-context: 73505107f7c673cd550a561aeb6271f152c483b6
1913+
React-jserrorhandler: dfe9b96e99a93d4f4858bad66d5bc4813a87a21a
1914+
React-jsi: b187c826e5bda25afb36ede4c54c146cd50c9d6c
1915+
React-jsiexecutor: ac8478b6c5f53bcf411a66bf4461e923dafeb0bd
1916+
React-jsinspector: 3ddb69299335dfeceb01ad4b9c3eb2b5945cd149
1917+
React-jsitracing: cac972ccc097db399df8044e49add8e5b25cb34a
1918+
React-logger: 80d87daf2f98bf95ab668b79062c1e0c3f0c2f8a
1919+
React-Mapbuffer: acffb35a53a5f474ede09f082ac609b41aafab2e
1920+
React-microtasksnativemodule: 8316f77469bf116d89e800e87de19eda7830339c
1921+
react-native-bottom-tabs: 8aab64074997748a2459dc8707827bdbc4dc9252
1922+
react-native-safe-area-context: f2beaaf96e5c342a9c1dbdd5bc4eeb717424fb80
19481923
React-nativeconfig: 8c83d992b9cc7d75b5abe262069eaeea4349f794
1949-
React-NativeModulesApple: b8465afc883f5bf3fe8bac3767e394d581a5f123
1924+
React-NativeModulesApple: f2fae67dde85ef5d8985bfa04eaa120b52b1c24a
19501925
React-perflogger: 59e1a3182dca2cee7b9f1f7aab204018d46d1914
1951-
React-performancetimeline: a9d05533ff834c6aa1f532e05e571f3fd2e3c1ed
1926+
React-performancetimeline: 3e3f5c5576fe1cc2dd5fcfb1ae2046d5dceda3d7
19521927
React-RCTActionSheet: d80e68d3baa163e4012a47c1f42ddd8bcd9672cc
1953-
React-RCTAnimation: bde981f6bd7f8493696564da9b3bd05721d3b3cc
1954-
React-RCTAppDelegate: e5865dbf46ddec6d9ed9310a05094d13f9bb043f
1955-
React-RCTBlob: e492d54533e61a81f2601494a6f393b3e15e33b9
1956-
React-RCTFabric: e6ef266a60e885a0548b0f7a5e9737f42ccd596b
1957-
React-RCTImage: 90448d2882464af6015ed57c98f463f8748be465
1958-
React-RCTLinking: 1bd95d0a704c271d21d758e0f0388cced768d77d
1959-
React-RCTNetwork: 218af6e63eb9b47935cc5a775b7a1396cf10ff91
1960-
React-RCTSettings: e10b8e42b0fce8a70fbf169de32a2ae03243ef6b
1961-
React-RCTText: e7bf9f4997a1a0b45c052d4ad9a0fe653061cf29
1962-
React-RCTVibration: 5b70b7f11e48d1c57e0d4832c2097478adbabe93
1928+
React-RCTAnimation: 051f0781709c5ed80ba8aa2b421dfb1d72a03162
1929+
React-RCTAppDelegate: 0b2a626838fb828acdaf0789a18d681cf9664a61
1930+
React-RCTBlob: e949797c162421e363f93bfd8b546b7e632ba847
1931+
React-RCTFabric: 9398c6720ec94e047737909e00452e30594164bc
1932+
React-RCTImage: b73149c0cd54b641dba2d6250aaf168fee784d9f
1933+
React-RCTLinking: 23e519712285427e50372fbc6e0265d422abf462
1934+
React-RCTNetwork: a5d06d122588031989115f293654b13353753630
1935+
React-RCTSettings: 87d03b5d94e6eadd1e8c1d16a62f790751aafb55
1936+
React-RCTText: 75e9dd39684f4bcd1836134ac2348efaca7437b3
1937+
React-RCTVibration: 033c161fe875e6fa096d0d9733c2e2501682e3d4
19631938
React-rendererconsistency: f620c6e003e3c4593e6349d8242b8aeb3d4633f0
1964-
React-rendererdebug: e697680f4dd117becc5daf9ea9800067abcee91c
1939+
React-rendererdebug: 5be7b834677b2a7a263f4d2545f0d4966cafad82
19651940
React-rncore: c22bd84cc2f38947f0414fab6646db22ff4f80cd
1966-
React-RuntimeApple: 352013c169b30fd6a1c83acc39c16ac27fecf42e
1967-
React-RuntimeCore: 704ebf1cc6bc7f5b72da4a7740a4d1520c66bee5
1941+
React-RuntimeApple: a686e45ca18a703447a5cf173ae1ad51e58abe84
1942+
React-RuntimeCore: 1c68670cd7edebfd41affffb1f4464712a428e73
19681943
React-runtimeexecutor: ea90d8e3a9e0f4326939858dafc6ab17c031a5d3
1969-
React-runtimescheduler: 86b04703f6cb40f5d30a639a28aaee405032e75a
1970-
React-utils: 546831c4f1be57fac614f68de34ac8763e67db55
1971-
ReactCodegen: 54f07f54275a16f8e3a32cbdd62bf008b0869c9c
1972-
ReactCommon: 8377a2a5504f72e284ce1b1cd207d8455bdbfdf3
1973-
ReactNativeHost: a3cd2bc15b6deac7439318607ce5637d8a93a117
1974-
ReactTestApp-DevSupport: ce66fc1bbcf598d7e90616db390a0274c13e14e7
1944+
React-runtimescheduler: 7774e739c3a7855db01f34ed1714c0bc0be5f041
1945+
React-utils: 76fd4e86f1f3a4217b86a70fd067ffad9984c669
1946+
ReactCodegen: 2e8616099824063496ecff2abe18d223a59b89ce
1947+
ReactCommon: 7d4342b3f8c0ed7e0ac14ae4da79d1fc5e650e0c
1948+
ReactNativeHost: bfb0e02bf61df8dfa78e9c7a8a0129519e6f0c74
1949+
ReactTestApp-DevSupport: 4ebd8dbae375a3a265d37c59179d281f2f1609d8
19751950
ReactTestApp-Resources: 9c387cfe7185736e6a9045e5aa3e085367be6aa3
1976-
RNGestureHandler: 492b1d415a25506d1dc612e6a14932b1e697d835
1977-
RNScreens: 16a61c0a9fe4cd69af6489b8d10ba580b5e22ed0
1978-
RNVectorIcons: a1344e212e80e6e0f4537a9960148201175f4225
1951+
RNGestureHandler: 4895ef926ab1c16473384aa8b3e5f39c318ed2b6
1952+
RNScreens: a4747a8a6847adfd9426b2d5b10a8fc68c130fdf
1953+
RNVectorIcons: 0d15b83d2906dbc2a786ff58eb46475576e2cf96
19791954
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
19801955
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
19811956
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d

apps/example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"dependencies": {
1919
"@bottom-tabs/react-navigation": "*",
2020
"@callstack/react-native-visionos": "^0.75.0",
21-
"@react-navigation/bottom-tabs": "^6.6.1",
21+
"@react-navigation/bottom-tabs": "7.2.0",
2222
"@react-navigation/native": "7.0.4",
2323
"@react-navigation/native-stack": "^7.1.1",
2424
"@react-navigation/stack": "^7.0.6",

apps/example/src/App.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import NativeBottomTabsEmbeddedStacks from './Examples/NativeBottomTabsEmbeddedS
2828
import NativeBottomTabsSVGs from './Examples/NativeBottomTabsSVGs';
2929
import NativeBottomTabsRemoteIcons from './Examples/NativeBottomTabsRemoteIcons';
3030
import NativeBottomTabsUnmounting from './Examples/NativeBottomTabsUnmounting';
31+
import NativeBottomTabsCustomTabBar from './Examples/NativeBottomTabsCustomTabBar';
3132

3233
const FourTabsIgnoreSafeArea = () => {
3334
return <FourTabs ignoresTopSafeArea />;
@@ -136,6 +137,10 @@ const examples = [
136137
component: NativeBottomTabsRemoteIcons,
137138
name: 'Native Bottom Tabs with SVG Remote Icons',
138139
},
140+
{
141+
component: NativeBottomTabsCustomTabBar,
142+
name: 'Native Bottom Tabs with Custom Tab Bar',
143+
},
139144
{ component: NativeBottomTabs, name: 'Native Bottom Tabs' },
140145
{ component: JSBottomTabs, name: 'JS Bottom Tabs' },
141146
{
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Article } from '../Screens/Article';
2+
import { Albums } from '../Screens/Albums';
3+
import { Contacts } from '../Screens/Contacts';
4+
import { Chat } from '../Screens/Chat';
5+
import {
6+
createNativeBottomTabNavigator,
7+
type BottomTabBarProps,
8+
} from '@bottom-tabs/react-navigation';
9+
import { BottomTabBar } from '@react-navigation/bottom-tabs';
10+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
11+
12+
const Tab = createNativeBottomTabNavigator();
13+
14+
const CustomTabBar = (props: BottomTabBarProps) => {
15+
const insets = useSafeAreaInsets();
16+
// @ts-ignore Typescript thinks that props don't match but they are actually the same under the hood
17+
return <BottomTabBar insets={insets} {...props} />;
18+
};
19+
20+
function NativeBottomTabsCustomTabBar() {
21+
return (
22+
<Tab.Navigator tabBar={CustomTabBar}>
23+
<Tab.Screen name="Article" component={Article} />
24+
<Tab.Screen name="Albums" component={Albums} />
25+
<Tab.Screen name="Contacts" component={Contacts} />
26+
<Tab.Screen
27+
name="Chat"
28+
component={Chat}
29+
options={{
30+
tabBarBadge: '3',
31+
}}
32+
/>
33+
</Tab.Navigator>
34+
);
35+
}
36+
37+
export default NativeBottomTabsCustomTabBar;

packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class ReactBottomNavigationView(context: Context) : LinearLayout(context) {
8080
))
8181

8282
post {
83-
addOnLayoutChangeListener { _, left, top, right, bottom,
83+
layoutHolder.addOnLayoutChangeListener { _, left, top, right, bottom,
8484
_, _, _, _ ->
8585
val newWidth = right - left
8686
val newHeight = bottom - top
@@ -207,6 +207,14 @@ class ReactBottomNavigationView(context: Context) : LinearLayout(context) {
207207
}
208208
}
209209

210+
fun setTabBarHidden(isHidden: Boolean) {
211+
if (isHidden) {
212+
bottomNavigation.visibility = GONE
213+
} else {
214+
bottomNavigation.visibility = VISIBLE
215+
}
216+
}
217+
210218
fun updateItems(items: MutableList<TabInfo>) {
211219
// If an item got removed, let's re-add all items
212220
if (items.size < this.items.size) {

packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabViewImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ data class TabInfo(
1515
val badge: String,
1616
val activeTintColor: Int?,
1717
val hidden: Boolean,
18-
val testID: String?,
18+
val testID: String?
1919
)
2020

2121
class RCTTabViewImpl {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ class RCTTabViewManager(context: ReactApplicationContext) :
141141
view?.disablePageAnimations = value
142142
}
143143

144+
override fun setTabBarHidden(view: ReactBottomNavigationView?, value: Boolean) {
145+
view?.setTabBarHidden(value)
146+
}
147+
144148
// iOS Methods
145149
override fun setTranslucent(view: ReactBottomNavigationView?, value: Boolean) {
146150
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ class RCTTabViewManager(context: ReactApplicationContext) : ViewGroupManager<Rea
117117
view.disablePageAnimations = flag
118118
}
119119

120+
@ReactProp(name = "tabBarHidden")
121+
fun setTabBarHidden(view: ReactBottomNavigationView, flag: Boolean) {
122+
view.setTabBarHidden(flag)
123+
}
124+
120125
// iOS Props
121126
@ReactProp(name = "sidebarAdaptable")
122127
fun setSidebarAdaptable(view: ReactBottomNavigationView, flag: Boolean) {

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,22 +146,27 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
146146
if (oldViewProps.inactiveTintColor != newViewProps.inactiveTintColor) {
147147
_tabViewProvider.inactiveTintColor = RCTUIColorFromSharedColor(newViewProps.inactiveTintColor);
148148
}
149-
149+
150150
if (oldViewProps.hapticFeedbackEnabled != newViewProps.hapticFeedbackEnabled) {
151151
_tabViewProvider.hapticFeedbackEnabled = newViewProps.hapticFeedbackEnabled;
152152
}
153-
153+
154154
if (oldViewProps.fontSize != newViewProps.fontSize) {
155155
_tabViewProvider.fontSize = [NSNumber numberWithInt:newViewProps.fontSize];
156156
}
157-
157+
158158
if (oldViewProps.fontWeight != newViewProps.fontWeight) {
159159
_tabViewProvider.fontWeight = RCTNSStringFromStringNilIfEmpty(newViewProps.fontWeight);
160160
}
161-
161+
162162
if (oldViewProps.fontFamily != newViewProps.fontFamily) {
163163
_tabViewProvider.fontFamily = RCTNSStringFromStringNilIfEmpty(newViewProps.fontFamily);
164164
}
165+
166+
if (oldViewProps.tabBarHidden != newViewProps.tabBarHidden) {
167+
_tabViewProvider.tabBarHidden = newViewProps.tabBarHidden;
168+
}
169+
165170

166171
[super updateProps:props oldProps:oldProps];
167172
}

0 commit comments

Comments
 (0)