refactor: move tabBarOptions to options for material top tabs

This commit is contained in:
Satyajit Sahoo
2021-03-06 22:49:42 +01:00
parent 2bc4882692
commit e127c84ae9
5 changed files with 131 additions and 98 deletions

View File

@@ -106,7 +106,8 @@ export type BottomTabNavigationOptions = HeaderOptions & {
/**
* Title string of a tab displayed in the tab bar
* or a function that given { focused: boolean, color: string, position: 'below-icon' | 'beside-icon' } returns a React.Node to display in tab bar.
* When undefined, scene title is used. To hide, see tabBarOptions.showLabel in the previous section.
*
* When undefined, scene title is used. Use `tabBarShowLabel` to hide the label.
*/
tabBarLabel?:
| string

View File

@@ -17,5 +17,4 @@ export type {
MaterialTopTabNavigationProp,
MaterialTopTabScreenProps,
MaterialTopTabBarProps,
MaterialTopTabBarOptions,
} from './types';

View File

@@ -1,9 +1,5 @@
import type { StyleProp, ViewStyle, TextStyle } from 'react-native';
import type {
TabBar,
SceneRendererProps,
TabView,
} from 'react-native-tab-view';
import type { SceneRendererProps, TabView } from 'react-native-tab-view';
import type {
ParamListBase,
Descriptor,
@@ -69,7 +65,8 @@ export type MaterialTopTabNavigationOptions = {
/**
* Title string of a tab displayed in the tab bar
* or a function that given { focused: boolean, color: string } returns a React.Node, to display in tab bar.
* When undefined, scene title is used. To hide, see tabBarOptions.showLabel in the previous section.
*
* When undefined, scene title is used. Use `tabBarShowLabel` to hide the label.
*/
tabBarLabel?:
| string
@@ -90,6 +87,88 @@ export type MaterialTopTabNavigationOptions = {
* ID to locate this tab button in tests.
*/
tabBarTestID?: string;
/**
* Color for the icon and label in the active tab.
*/
tabBarActiveTintColor?: string;
/**
* Color for the icon and label in the inactive tabs.
*/
tabBarInactiveTintColor?: string;
/**
* Color for material ripple (Android >= 5.0 only).
*/
tabBarPressColor?: string;
/**
* Opacity for pressed tab (iOS and Android < 5.0 only).
*/
tabBarPressOpacity?: number;
/**
* Whether the tab label should be visible. Defaults to `true`.
*/
tabBarShowLabel?: boolean;
/**
* Whether the tab icon should be visible. Defaults to `false`.
*/
tabBarShowIcon?: boolean;
/**
* Whether label font should scale to respect Text Size accessibility settings.
*/
tabBarAllowFontScaling?: boolean;
/**
* Boolean indicating whether the tab bar bounces when overscrolling.
*/
tabBarBounces?: boolean;
/**
* Boolean indicating whether to make the tab bar scrollable.
*
* If you set this to `true`, you should also specify a width in `tabBarItemStyle` to improve the performance of initial render.
*/
tabBarScrollEnabled?: boolean;
/**
* Style object for the tab icon container.
*/
tabBarIconStyle?: StyleProp<ViewStyle>;
/**
* Style object for the tab label.
*/
tabBarLabelStyle?: StyleProp<TextStyle>;
/**
* Style object for the individual tab items.
*/
tabBarItemStyle?: StyleProp<ViewStyle>;
/**
* Style object for the tab bar indicator.
*/
tabBarIndicatorStyle?: StyleProp<ViewStyle>;
/**
* Style object for the view containing the tab bar indicator.
*/
tabBarIndicatorContainerStyle?: StyleProp<ViewStyle>;
/**
* Style object for the view containing the tab items.
*/
tabBarContentContainerStyle?: StyleProp<ViewStyle>;
/**
* Style object for the the tab bar.
*/
tabBarStyle?: StyleProp<ViewStyle>;
};
export type MaterialTopTabDescriptor = Descriptor<
@@ -135,68 +214,17 @@ export type MaterialTopTabNavigationConfig = Partial<
* Function that returns a React element to display as the tab bar.
*/
tabBar?: (props: MaterialTopTabBarProps) => React.ReactNode;
/**
* Options for the tab bar which will be passed as props to the tab bar component.
*/
tabBarOptions?: MaterialTopTabBarOptions;
/**
* Position of the tab bar. Defaults to `top`.
*/
tabBarPosition?: 'top' | 'bottom';
};
export type MaterialTopTabBarOptions = Partial<
Omit<
React.ComponentProps<typeof TabBar>,
| 'navigationState'
| 'activeColor'
| 'inactiveColor'
| 'renderLabel'
| 'renderIcon'
| 'getLabelText'
| 'getAccessibilityLabel'
| 'getTestID'
| 'onTabPress'
| 'onTabLongPress'
| keyof SceneRendererProps
>
> & {
/**
* Color for the icon and label in the active tab.
*/
activeTintColor?: string;
/**
* Color for the icon and label in the inactive tabs.
*/
inactiveTintColor?: string;
/**
* Style object for the tab icon container.
*/
iconStyle?: StyleProp<ViewStyle>;
/**
* Style object for the tab label.
*/
labelStyle?: StyleProp<TextStyle>;
/**
* Whether the tab label should be visible. Defaults to `true`.
*/
showLabel?: boolean;
/**
* Whether the tab icon should be visible. Defaults to `false`.
*/
showIcon?: boolean;
/**
* Whether label font should scale to respect Text Size accessibility settings.
*/
allowFontScaling?: boolean;
export type MaterialTopTabBarProps = SceneRendererProps & {
state: TabNavigationState<ParamListBase>;
navigation: NavigationHelpers<
ParamListBase,
MaterialTopTabNavigationEventMap
>;
descriptors: MaterialTopTabDescriptorMap;
};
export type MaterialTopTabBarProps = MaterialTopTabBarOptions &
SceneRendererProps & {
state: TabNavigationState<ParamListBase>;
navigation: NavigationHelpers<
ParamListBase,
MaterialTopTabNavigationEventMap
>;
descriptors: MaterialTopTabDescriptorMap;
};

View File

@@ -6,35 +6,39 @@ import Color from 'color';
import type { MaterialTopTabBarProps } from '../types';
export default function TabBarTop(props: MaterialTopTabBarProps) {
export default function TabBarTop({
state,
navigation,
descriptors,
...rest
}: MaterialTopTabBarProps) {
const { colors } = useTheme();
const {
state,
navigation,
descriptors,
activeTintColor = colors.text,
inactiveTintColor = Color(activeTintColor).alpha(0.5).rgb().string(),
allowFontScaling = true,
showIcon = false,
showLabel = true,
pressColor = Color(activeTintColor).alpha(0.08).rgb().string(),
iconStyle,
labelStyle,
indicatorStyle,
style,
...rest
} = props;
const focusedOptions = descriptors[state.routes[state.index].key].options;
const activeColor = focusedOptions.tabBarActiveTintColor ?? colors.text;
const inactiveColor =
focusedOptions.tabBarInactiveTintColor ??
Color(activeColor).alpha(0.5).rgb().string();
return (
<TabBar
{...rest}
navigationState={state}
activeColor={activeTintColor}
inactiveColor={inactiveTintColor}
indicatorStyle={[{ backgroundColor: colors.primary }, indicatorStyle]}
style={[{ backgroundColor: colors.card }, style]}
pressColor={pressColor}
scrollEnabled={focusedOptions.tabBarScrollEnabled}
bounces={focusedOptions.tabBarBounces}
activeColor={activeColor}
inactiveColor={inactiveColor}
pressColor={focusedOptions.tabBarPressColor}
pressOpacity={focusedOptions.tabBarPressOpacity}
tabStyle={focusedOptions.tabBarItemStyle}
indicatorStyle={[
{ backgroundColor: colors.primary },
focusedOptions.tabBarIndicatorStyle,
]}
indicatorContainerStyle={focusedOptions.tabBarIndicatorContainerStyle}
contentContainerStyle={focusedOptions.tabBarContentContainerStyle}
style={[{ backgroundColor: colors.card }, focusedOptions.tabBarStyle]}
getAccessibilityLabel={({ route }) =>
descriptors[route.key].options.tabBarAccessibilityLabel
}
@@ -57,26 +61,29 @@ export default function TabBarTop(props: MaterialTopTabBarProps) {
})
}
renderIcon={({ route, focused, color }) => {
if (showIcon === false) {
const { options } = descriptors[route.key];
if (options.tabBarShowIcon === false) {
return null;
}
const { options } = descriptors[route.key];
if (options.tabBarIcon !== undefined) {
const icon = options.tabBarIcon({ focused, color });
return <View style={[styles.icon, iconStyle]}>{icon}</View>;
return (
<View style={[styles.icon, options.tabBarIconStyle]}>{icon}</View>
);
}
return null;
}}
renderLabel={({ route, focused, color }) => {
if (showLabel === false) {
const { options } = descriptors[route.key];
if (options.tabBarShowLabel === false) {
return null;
}
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
@@ -87,8 +94,8 @@ export default function TabBarTop(props: MaterialTopTabBarProps) {
if (typeof label === 'string') {
return (
<Text
style={[styles.label, { color }, labelStyle]}
allowFontScaling={allowFontScaling}
style={[styles.label, { color }, options.tabBarLabelStyle]}
allowFontScaling={options.tabBarAllowFontScaling}
>
{label}
</Text>

View File

@@ -27,7 +27,6 @@ export default function MaterialTopTabView({
pager,
lazyPlaceholder,
tabBar = (props: MaterialTopTabBarProps) => <MaterialTopTabBar {...props} />,
tabBarOptions,
state,
navigation,
descriptors,
@@ -38,7 +37,6 @@ export default function MaterialTopTabView({
const renderTabBar = (props: SceneRendererProps) => {
return tabBar({
...tabBarOptions,
...props,
state: state,
navigation: navigation,