Skip to content

Commit 6a53979

Browse files
committed
Add docs for native bottom tabs
1 parent 149cf34 commit 6a53979

File tree

3 files changed

+1165
-777
lines changed

3 files changed

+1165
-777
lines changed
Lines changed: 383 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
1+
---
2+
id: native-bottom-tab-navigator
3+
title: Native Bottom Tabs Navigator
4+
sidebar_label: Native Bottom Tabs
5+
---
6+
7+
:::warning
8+
9+
This navigator is currently experimental. The API will change in future releases.
10+
11+
Currently only iOS and Android are supported. Use [`createBottomTabNavigator`](bottom-tab-navigator.md) for web support.
12+
13+
:::
14+
15+
Native Bottom Tabs displays screens with a tab bar to switch between them.
16+
17+
The navigator uses native components on iOS and Android for better platform integration. On iOS, it uses `UITabBarController` and on Android, it uses `BottomNavigationView`.
18+
19+
## Installation
20+
21+
To use this navigator, ensure that you have [`@react-navigation/native` and its dependencies (follow this guide)](getting-started.md), then install [`@react-navigation/bottom-tabs`](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs):
22+
23+
```bash npm2yarn
24+
npm install @react-navigation/bottom-tabs
25+
```
26+
27+
## Usage
28+
29+
To use this navigator, import it from `@react-navigation/bottom-tabs/unstable`:
30+
31+
<Tabs groupId="config" queryString="config">
32+
<TabItem value="static" label="Static" default>
33+
34+
```js name="Bottom Tab Navigator"
35+
import { createNativeBottomTabNavigator } from '@react-navigation/bottom-tabs/unstable';
36+
37+
const MyTabs = createNativeBottomTabNavigator({
38+
screens: {
39+
Home: HomeScreen,
40+
Profile: ProfileScreen,
41+
},
42+
});
43+
```
44+
45+
</TabItem>
46+
<TabItem value="dynamic" label="Dynamic">
47+
48+
```js name="Bottom Tab Navigator"
49+
import { createNativeBottomTabNavigator } from '@react-navigation/bottom-tabs/unstable';
50+
51+
const Tab = createNativeBottomTabNavigator();
52+
53+
function MyTabs() {
54+
return (
55+
<Tab.Navigator>
56+
<Tab.Screen name="Home" component={HomeScreen} />
57+
<Tab.Screen name="Profile" component={ProfileScreen} />
58+
</Tab.Navigator>
59+
);
60+
}
61+
```
62+
63+
</TabItem>
64+
</Tabs>
65+
66+
## API Definition
67+
68+
### Props
69+
70+
In addition to the [common props](navigator.md#configuration) shared by all navigators, the bottom tab navigator accepts the following additional props:
71+
72+
#### `backBehavior`
73+
74+
This controls what happens when `goBack` is called in the navigator. This includes pressing the device's back button or back gesture on Android.
75+
76+
It supports the following values:
77+
78+
- `firstRoute` - return to the first screen defined in the navigator (default)
79+
- `initialRoute` - return to initial screen passed in `initialRouteName` prop, if not passed, defaults to the first screen
80+
- `order` - return to screen defined before the focused screen
81+
- `history` - return to last visited screen in the navigator; if the same screen is visited multiple times, the older entries are dropped from the history
82+
- `fullHistory` - return to last visited screen in the navigator; doesn't drop duplicate entries unlike `history` - this behavior is useful to match how web pages work
83+
- `none` - do not handle back button
84+
85+
### Options
86+
87+
The following [options](screen-options.md) can be used to configure the screens in the navigator. These can be specified under `screenOptions` prop of `Tab.navigator` or `options` prop of `Tab.Screen`.
88+
89+
#### `title`
90+
91+
Generic title that can be used as a fallback for `headerTitle` and `tabBarLabel`.
92+
93+
#### `tabBarSystemItem`
94+
95+
Uses iOS built-in tab bar items with standard iOS styling and localized titles.
96+
97+
If set to `search`, it's positioned next to the tab bar on iOS 26 and above.
98+
99+
The [`tabBarIcon`](#tabbaricon) and [`tabBarLabel`](#tabbarlabel) options will override the icon and label from the system item. If you want to keep the system behavior on iOS, but need to provide icon and label for other platforms, use `Platform.OS` or `Platform.select` to conditionally set `undefined` for `tabBarIcon` and `tabBarLabel` on iOS.
100+
101+
#### `tabBarLabel`
102+
103+
Title string of a tab displayed in the tab bar.
104+
105+
Overrides the label provided by [`tabBarSystemItem`](#tabbarsystemitem) on iOS.
106+
107+
If not provided, or set to `undefined`:
108+
109+
- The system values are used if [`tabBarSystemItem`](#tabbarsystemitem) is set on iOS.
110+
- Otherwise, it falls back to the [`title`](#title) or route name.
111+
112+
#### `tabBarLabelVisibilityMode`
113+
114+
The label visibility mode for the tab bar items. Supported values:
115+
116+
- `auto` - the system decides when to show or hide labels
117+
- `selected` - labels are shown only for the selected tab
118+
- `labeled` - labels are always shown
119+
- `unlabeled` - labels are never shown
120+
121+
Only supported on Android.
122+
123+
#### `tabBarLabelStyle`
124+
125+
Style object for the tab label. Supported properties:
126+
127+
- `fontFamily`
128+
- `fontSize`
129+
- `fontWeight`
130+
- `fontStyle`
131+
132+
Example:
133+
134+
```js
135+
tabBarLabelStyle: {
136+
fontSize: 16,
137+
fontFamily: 'Georgia',
138+
fontWeight: 300,
139+
},
140+
```
141+
142+
#### `tabBarIcon`
143+
144+
Icon to display for the tab. It overrides the icon provided by [`tabBarSystemItem`](#tabbarsystemitem) on iOS.
145+
146+
It can be an icon object or a function that given `{ focused: boolean, color: string, size: number }` returns an icon object.
147+
148+
The icon can be of following types:
149+
150+
- Local image - Supported on iOS and Android
151+
152+
```js
153+
tabBarIcon: {
154+
type: 'image',
155+
source: require('./path/to/icon.png'),
156+
}
157+
```
158+
159+
On iOS, you can additionally pass a `tinted` property to control whether the icon should be tinted with the active/inactive color:
160+
161+
```js
162+
tabBarIcon: {
163+
type: 'image',
164+
source: require('./path/to/icon.png'),
165+
tinted: false, // defaults to false
166+
}
167+
```
168+
169+
The image is tinted by default.
170+
171+
- [SF Symbols](https://developer.apple.com/sf-symbols/) name - Supported on iOS
172+
173+
```js
174+
tabBarIcon: {
175+
type: 'sfSymbol',
176+
name: 'heart',
177+
}
178+
```
179+
180+
- Drawable resource name - Supported on Android
181+
182+
```js
183+
tabBarIcon: {
184+
type: 'drawable',
185+
name: 'sunny',
186+
}
187+
```
188+
189+
To render different icons for active and inactive states, you can use a function:
190+
191+
```js
192+
tabBarIcon: ({ focused }) => {
193+
return {
194+
type: 'sfSymbol',
195+
name: focused ? 'heart' : 'heart-outline',
196+
};
197+
},
198+
```
199+
200+
This is only supported on iOS. On Android, the icon specified for inactive state will be used for both active and inactive states.
201+
202+
To provide different icons for different platforms, you can use [`Platform.select`](https://reactnative.dev/docs/platform-specific-code):
203+
204+
```js
205+
tabBarIcon: Platform.select({
206+
ios: {
207+
type: 'sfSymbol',
208+
name: 'heart',
209+
},
210+
android: {
211+
type: 'drawable',
212+
name: 'heart_icon',
213+
},
214+
});
215+
```
216+
217+
#### `tabBarBadge`
218+
219+
Text to show in a badge on the tab icon. Accepts a `string` or a `number`.
220+
221+
#### `tabBarBadgeStyle`
222+
223+
Style for the badge on the tab icon. Supported properties:
224+
225+
- `backgroundColor`
226+
- `color`
227+
228+
Example:
229+
230+
```js
231+
tabBarBadgeStyle: {
232+
backgroundColor: 'yellow',
233+
color: 'black',
234+
},
235+
```
236+
237+
#### `tabBarActiveTintColor`
238+
239+
Color for the icon and label in the active tab.
240+
241+
#### `tabBarInactiveTintColor`
242+
243+
Color for the icon and label in the inactive tabs.
244+
245+
Only supported on Android.
246+
247+
#### `tabBarActiveIndicatorColor`
248+
249+
Background color of the active indicator.
250+
251+
Only supported on Android.
252+
253+
#### `tabBarActiveIndicatorEnabled`
254+
255+
Whether the active indicator should be used. Defaults to `true`.
256+
257+
Only supported on Android.
258+
259+
#### `tabBarRippleColor`
260+
261+
Color of the ripple effect when pressing a tab.
262+
263+
Only supported on Android.
264+
265+
#### `tabBarStyle`
266+
267+
Style object for the tab bar. Supported properties:
268+
269+
- `backgroundColor` - Only supported on Android and iOS 18 and below.
270+
- `shadowColor` - Only supported on iOS 18 and below.
271+
272+
#### `tabBarControllerMode`
273+
274+
The display mode for the tab bar. Supported values:
275+
276+
- `auto` - the system sets the display mode based on the tab’s content
277+
- `tabBar` - the system displays the content only as a tab bar
278+
- `tabSidebar` - the tab bar is displayed as a sidebar
279+
280+
Only supported on iOS 18 and above. Not supported on tvOS.
281+
282+
#### `tabBarMinimizeBehavior`
283+
284+
The minimize behavior for the tab bar. Supported values:
285+
286+
- `auto` - resolves to the system default minimize behavior
287+
- `never` - the tab bar does not minimize
288+
- `onScrollDown` - the tab bar minimizes when scrolling down and
289+
expands when scrolling back up
290+
- `onScrollUp` - the tab bar minimizes when scrolling up and expands
291+
when scrolling back down
292+
293+
Only supported on iOS 26 and above.
294+
295+
#### `lazy`
296+
297+
Whether this screen should render only after the first time it's accessed. Defaults to `true`. Set it to `false` if you want to render the screen on the initial render of the navigator.
298+
299+
#### `popToTopOnBlur`
300+
301+
Boolean indicating whether any nested stack should be popped to the top of the stack when navigating away from this tab. Defaults to `false`.
302+
303+
It only works when there is a stack navigator (e.g. [stack navigator](stack-navigator.md) or [native stack navigator](native-stack-navigator.md)) nested under the tab navigator.
304+
305+
### Header related options
306+
307+
The navigator renders a native stack header. It supports most of the [header related options supported in `@react-navigation/native-stack`](native-stack-navigator.md#headerrelatedoptions) apart from the options related to the back button (prefixed with `headerBack`).
308+
309+
### Events
310+
311+
The navigator can [emit events](navigation-events.md) on certain actions. Supported events are:
312+
313+
#### `tabPress`
314+
315+
This event is fired when the user presses the tab button for the current screen in the tab bar. By default a tab press does several things:
316+
317+
- If the tab is not focused, tab press will focus that tab
318+
- If the tab is already focused:
319+
- If the screen for the tab renders a scroll view, you can use [`useScrollToTop`](use-scroll-to-top.md) to scroll it to top
320+
- If the screen for the tab renders a stack navigator, a `popToTop` action is performed on the stack
321+
322+
To prevent the default behavior, you can call `event.preventDefault`:
323+
324+
```js
325+
React.useEffect(() => {
326+
const unsubscribe = navigation.addListener('tabPress', (e) => {
327+
// Prevent default behavior
328+
e.preventDefault();
329+
330+
// Do something manually
331+
// ...
332+
});
333+
334+
return unsubscribe;
335+
}, [navigation]);
336+
```
337+
338+
#### `transitionStart`
339+
340+
This event is fired when the transition animation starts for the current screen.
341+
342+
Example:
343+
344+
```js
345+
React.useEffect(() => {
346+
const unsubscribe = navigation.addListener('transitionStart', (e) => {
347+
// Do something
348+
});
349+
350+
return unsubscribe;
351+
}, [navigation]);
352+
```
353+
354+
#### `transitionEnd`
355+
356+
This event is fired when the transition animation ends for the current screen.
357+
358+
Example:
359+
360+
```js
361+
React.useEffect(() => {
362+
const unsubscribe = navigation.addListener('transitionEnd', (e) => {
363+
// Do something
364+
});
365+
366+
return unsubscribe;
367+
}, [navigation]);
368+
```
369+
370+
### Helpers
371+
372+
The tab navigator adds the following methods to the navigation object:
373+
374+
#### `jumpTo`
375+
376+
Navigates to an existing screen in the tab navigator. The method accepts following arguments:
377+
378+
- `name` - _string_ - Name of the route to jump to.
379+
- `params` - _object_ - Screen params to use for the destination route.
380+
381+
```js
382+
navigation.jumpTo('Profile', { owner: 'Michaś' });
383+
```

0 commit comments

Comments
 (0)