You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A cross-platform Drawer component for React Native implemented using [`react-native-gesture-handler`](https://docs.swmansion.com/react-native-gesture-handler/) and [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/) on native platforms and CSS transitions on Web.
A cross-platform Drawer component for React Native implemented using [`react-native-gesture-handler`](https://docs.swmansion.com/react-native-gesture-handler/) and [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/) on native platforms and CSS transitions on Web.
12
20
13
21
If you need React Navigation integration, e.g. show screens in the drawer and be able to navigate between them using `navigation.navigate` etc, use [Drawer Navigator](drawer-navigator.md) instead.
@@ -528,21 +528,32 @@ Whether the tab icon should be visible. Defaults to `false`.
528
528
529
529
Function that returns a React element to use as a badge for the tab.
530
530
531
+
#### `tabBarVariant`
532
+
533
+
Variant of the tab bar. Supported values are:
534
+
535
+
-`'primary'` (default): the indicator matches the label & icon width and is centered under the tab, active color defaults to the theme's primary color.
536
+
-`'secondary'`: the indicator spans the full tab width, active color defaults to the theme's text color.
537
+
531
538
#### `tabBarIndicator`
532
539
533
-
Function that returns a React element as the tab bar indicator.
540
+
Function that returns a React element as the tab bar indicator. It receives the same props that you'd pass to [`TabBarIndicator`](tab-view.md#tabbarindicator) from `react-native-tab-view`.
534
541
535
542
#### `tabBarIndicatorStyle`
536
543
537
544
Style object for the tab bar indicator.
538
545
539
-
The indicator takes the same width as the tab item by default. It can be customized in a few ways:
546
+
The default width of the indicator depends on [`tabBarVariant`](#tabbarvariant):
547
+
548
+
- With `tabBarVariant: 'primary'` (default), the indicator matches the width of the tab's label & icon and is centered under the tab.
549
+
- With `tabBarVariant: 'secondary'`, the indicator spans the full tab width.
540
550
541
-
- To make it smaller by a certain amount, you can add a horizontal margin, e.g. `{ marginHorizontal: 10 }`.
542
-
- Adding specific width will position the indicator at the left of the tab, e.g. `{ width: 20 }`.
543
-
- To center it in the tab when a custom width is specified, you can specify `margin` as `'auto'`, e.g. `{ width: 20, marginHorizontal: 'auto' }`.
551
+
You can customize the indicator in a few ways:
544
552
545
-
When the `tabStyle` has `width: 'auto'` and no explicit `width` is specified for the indicator, it is scaled to the width with `transform: [{ scaleX }]` for smooth animations. So specifying a `borderRadius` won't work as expected.
553
+
- To shrink it by a fixed amount, add a horizontal margin, e.g. `{ marginHorizontal: 10 }`.
554
+
- To give it a specific width, set `width`, e.g. `{ width: 20 }`. By default this aligns the indicator to the start.
555
+
- To center a custom-width indicator inside the tab, set `margin` to `'auto'`, e.g. `{ width: 20, marginHorizontal: 'auto' }`.
556
+
- To make the corners rounded, pass `borderRadius`,`borderTopLeftRadius`, or `borderTopRightRadius` etc. as a number, e.g. `{ borderRadius: 10 }`.
546
557
547
558
If you need more control, you can use [`tabBarIndicator`](#tabbarindicator) to render a custom indicator instead.
548
559
@@ -578,7 +589,7 @@ Boolean indicating whether the tab bar bounces when overscrolling.
578
589
579
590
Boolean indicating whether to make the tab bar scrollable.
580
591
581
-
If you set this to `true`, you should also specify a width in `tabBarItemStyle` to improve the performance of initial render.
592
+
When this is set to `true`, each tab is sized to fit its content by default. To use a fixed width instead, set `width` in `tabBarItemStyle`.
React Native Tab View is a cross-platform Tab View component for React Native implemented using [`react-native-pager-view`](https://github.com/callstack/react-native-viewpager) on Android & iOS, and [PanResponder](https://reactnative.dev/docs/panresponder) on Web, macOS, and Windows.
8
28
9
29
It follows material design guidelines by default, but you can also use your own custom tab bar or position the tab bar at the bottom.
If you need React Navigation integration, e.g. show screens in the tab bar and be able to navigate between them using `navigation.navigate` etc, use [Material Top Tab Navigator](material-top-tab-navigator.md) instead.
16
32
17
33
## Installation
@@ -596,13 +612,38 @@ return (
596
612
597
613
#### TabBar Props
598
614
615
+
##### `variant`
616
+
617
+
Variant of the tab bar. Supported values are:
618
+
619
+
-`'primary'` (default): the indicator matches the label & icon width and is centered under the tab, active color defaults to the theme's primary color.
620
+
-`'secondary'`: the indicator spans the full tab width, active color defaults to the theme's text color.
621
+
599
622
##### `renderTabBarItem`
600
623
601
-
Function which takes a `TabBarItemProps` object and returns a custom React Element to be used as a tab button.
624
+
Function that returns a custom React Element to be used as a tab button. By default, it uses [`TabBarItem`](#tabbaritem):
See [`TabBarIndicator`](#tabbarindicator) for the full list of props.
606
647
607
648
##### `onTabPress`
608
649
@@ -647,7 +688,7 @@ Opacity for pressed tab (iOS and Android < 5.0 only).
647
688
648
689
Boolean indicating whether to make the tab bar scrollable.
649
690
650
-
If you set `scrollEnabled`to`true`, you should also specify a `width` in `tabStyle` to improve the initial render.
691
+
When `scrollEnabled`is`true`, each tab is sized to fit its content by default. To use a fixed width instead, set `width` in `tabStyle`.
651
692
652
693
##### `bounces`
653
694
@@ -663,13 +704,17 @@ By default, all tab items take up the same pre-calculated width based on the wid
663
704
664
705
Style to apply to the active indicator.
665
706
666
-
The indicator takes the same width as the tab item by default. It can be customized in a few ways:
707
+
The default width of the indicator depends on the [`variant`](#variant):
667
708
668
-
- To make it smaller by a certain amount, you can add a horizontal margin, e.g. `{ marginHorizontal: 10 }`.
669
-
- Adding specific width will position the indicator at the left of the tab, e.g. `{ width: 20 }`.
670
-
- To center it in the tab when a custom width is specified, you can specify `margin` as `'auto'`, e.g. `{ width: 20, marginHorizontal: 'auto' }`.
709
+
- With `variant="primary"` (default), the indicator matches the width of the tab's label & icon and is centered under the tab.
710
+
- With `variant="secondary"`, the indicator spans the full tab width.
671
711
672
-
When the `tabStyle` has `width: 'auto'` and no explicit `width` is specified for the indicator, it is scaled to the width with `transform: [{ scaleX }]` for smooth animations. So specifying a `borderRadius` won't work as expected.
712
+
You can customize the indicator in a few ways:
713
+
714
+
- To shrink it by a fixed amount, add a horizontal margin, e.g. `{ marginHorizontal: 10 }`.
715
+
- To give it a specific width, set `width`, e.g. `{ width: 20 }`. By default this aligns the indicator to the start.
716
+
- To center a custom-width indicator inside the tab, set `margin` to `'auto'`, e.g. `{ width: 20, marginHorizontal: 'auto' }`.
717
+
- To make the corners rounded, pass `borderRadius`,`borderTopLeftRadius`, or `borderTopRightRadius` etc. as a number, e.g. `{ borderRadius: 10 }`.
673
718
674
719
If you need more control, you can use [`renderIndicator`](#renderindicator) to render a custom indicator instead.
675
720
@@ -800,6 +845,85 @@ badge: ({ route }) => (
800
845
801
846
Style to apply to the view wrapping each screen. You can pass this to override some default styles such as overflow clipping.
802
847
848
+
### `TabBarIndicator`
849
+
850
+
The default indicator component used by `TabBar`. It accepts the following props:
851
+
852
+
- `variant` - Variant of the indicator. Same values as [`TabBar`'s `variant`](#variant). Determines the default size and position behavior:
853
+
- `'primary'` (default): the indicator matches the label & icon width and is centered under the tab.
854
+
- `'secondary'`: the indicator spans the full tab width.
855
+
- `navigationState` - Same as [`TabView`'s `navigationState`](#navigationstate-required).
856
+
- `widths` - Array of indicator widths in pixels, one entry per route in the same order as `navigationState.routes`. These are the widths computed by `TabBar` based on the current `variant`, `indicatorStyle`, and measured tab/label widths.
857
+
- `offsets` - Array of indicator x offsets in pixels (absolute position within the tab bar), one entry per route in the same order as `navigationState.routes`. These already account for `gap`, padding, and any centering implied by `variant` or `marginHorizontal:'auto'`.
858
+
- `position` - Animated value that represents the current position. Goes from `0` to `routes.length-1` based on the swipe progress. Use this together with `widths` and `offsets` to interpolate the indicator's translation between tabs.
859
+
- `direction` - Layout direction of the tab bar. Either `'ltr'` or `'rtl'`.
860
+
- `jumpTo` - Function to jump to another tab, takes a `route.key` as its argument.
861
+
- `style` - Style to apply to the indicator. See [`indicatorStyle`](#indicatorstyle) for the full list of supported style customizations.
862
+
863
+
Internally, the indicator is rendered as multiple pieces to be able to support `borderRadius`, `borderTopLeftRadius`, or `borderTopRightRadius` etc. while still using `scale` transforms for animation. So it may not work with all style values properly as if it was a single view.
864
+
865
+
### `TabBarItem`
866
+
867
+
The default tab button component used by `TabBar`. It accepts the following props:
868
+
869
+
- `variant` - Variant of the tab. Same values as [`TabBar`'s `variant`](#variant). Determines the default active color.
870
+
- `route` - The route object for this tab.
871
+
- `navigationState` - Same as [`TabView`'s `navigationState`](#navigationstate-required).
872
+
- `position` - Animated value that represents the current position, used to interpolate the active/inactive label opacity.
873
+
- `activeColor` - Custom color for icon and label when the tab is active.
874
+
- `inactiveColor` - Custom color for icon and label when the tab is inactive.
875
+
- `pressColor` - Color for the material ripple (Android >= 5.0 only).
876
+
- `pressOpacity` - Opacity for pressed tab (iOS and Android < 5.0 only).
877
+
- `onPress` - Callback to invoke when the tab is pressed. The default `renderTabBarItem` wires this up to switch tabs.
878
+
- `onLongPress` - Callback to invoke when the tab is long-pressed.
879
+
- `onMeasureLayout` - Callback that receives the measured layout of the tab as `{ width, height }`. `TabBar` uses this to compute tab widths and indicator offsets when tabs are sized to their content (e.g. scrollable tab bars or `tabStyle: { width:'auto' }`).
880
+
- `onMeasureLabelLayout` - Callback that receives the measured layout of the label + icon as `{ width, height }`. `TabBar` uses this to size the indicator under the label for the `'primary'` variant.
881
+
- `android_ripple` - Allows you to customize the Android ripple effect on tab press. See [`PressableAndroidRippleConfig`](https://reactnative.dev/docs/pressable#rippleconfig).
882
+
- `style` - Style to apply to the tab container. Forwarded from `TabBar`'s `tabStyle`.
883
+
884
+
In addition to these, `TabBarItem` accepts all the [tab options](#options) (`label`, `labelText`, `labelStyle`, `icon`, `badge`, `href`, `accessibilityLabel`, `accessible`, `testID`, etc.).
885
+
886
+
If you render your own tab bar item via [`renderTabBarItem`](#rendertabbaritem) instead of using `TabBarItem`, you need to call `onMeasureLayout` and `onMeasureLabelLayout` for the indicator to work:
887
+
888
+
```tsx
889
+
constcontainerRef= useRef<View>(null);
890
+
constlabelRef= useRef<View>(null);
891
+
892
+
useLayoutEffect(() => {
893
+
containerRef.current?.measure((x, y, width, height) => {
894
+
onMeasureLayout({ width, height });
895
+
});
896
+
897
+
labelRef.current?.measure((x, y, width, height) => {
0 commit comments