Skip to content

Commit

Permalink
feat: move some props to screenOptions in material top tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
satya164 committed Jul 28, 2021
1 parent fdb3ede commit 5bfc396
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ function MaterialTopTabNavigator({
children,
screenListeners,
screenOptions,
swipeEnabled,
lazy,
lazyPlaceholder,
lazyPreloadDistance,
tabBarOptions,
...rest
}: Props) {
Expand All @@ -53,6 +56,8 @@ function MaterialTopTabNavigator({
tabBarIconStyle: tabBarOptions.iconStyle,
tabBarLabelStyle: tabBarOptions.labelStyle,
tabBarItemStyle: tabBarOptions.tabStyle,
tabBarBadge: tabBarOptions.renderBadge,
tabBarIndicator: tabBarOptions.renderIndicator,
tabBarIndicatorStyle: tabBarOptions.indicatorStyle,
tabBarIndicatorContainerStyle: tabBarOptions.indicatorContainerStyle,
tabBarContentContainerStyle: tabBarOptions.contentContainerStyle,
Expand Down Expand Up @@ -80,14 +85,24 @@ function MaterialTopTabNavigator({
);
}

if (typeof lazy === 'boolean') {
defaultScreenOptions.lazy = lazy;
const deprecatedProps = {
swipeEnabled,
lazy,
lazyPlaceholder,
lazyPreloadDistance,
} as const;

warnOnce(
true,
`Material Top Tab Navigator: 'lazy' in props is deprecated. Move it to 'screenOptions' instead.\n\nSee https://reactnavigation.org/docs/6.x/material-top-tab-navigator#lazy for more details.`
);
}
Object.entries(deprecatedProps).forEach(([propName, propValue]) => {
if (propValue !== undefined) {
// @ts-expect-error: Object.entries doesn't return strict types
defaultScreenOptions[propName] = propValue;

warnOnce(
true,
`Material Top Tab Navigator: '${propName}' in props is deprecated. Move it to 'screenOptions' instead.\n\nSee https://reactnavigation.org/docs/6.x/material-top-tab-navigator#${propName.toLowerCase()} for more details.`
);
}
});

const { state, descriptors, navigation, NavigationContent } =
useNavigationBuilder<
Expand Down
96 changes: 60 additions & 36 deletions packages/material-top-tabs/src/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,6 @@ export type MaterialTopTabNavigationOptions = {
*/
title?: string;

/**
* Whether this screens should render the first time it's accessed. Defaults to `false`.
*/
lazy?: boolean;

/**
* Function that returns a React element to render if this screen hasn't been rendered yet.
* The `lazy` option also needs to be enabled for this to work.
*
* This view is usually only shown for a split second. Keep it lightweight.
*
* By default, this renders null.
*/
lazyPlaceholder?: () => React.ReactNode;

/**
* 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.
Expand All @@ -92,11 +77,32 @@ export type MaterialTopTabNavigationOptions = {
| string
| ((props: { focused: boolean; color: string }) => React.ReactNode);

/**
* Accessibility label for the tab button. This is read by the screen reader when the user taps the tab.
* It's recommended to set this if you don't have a label for the tab.
*/
tabBarAccessibilityLabel?: string;

/**
* Whether label font should scale to respect Text Size accessibility settings.
*/
tabBarAllowFontScaling?: boolean;

/**
* Whether the tab label should be visible. Defaults to `true`.
*/
tabBarShowLabel?: boolean;

/**
* A function that given { focused: boolean, color: string } returns a React.Node to display in the tab bar.
*/
tabBarIcon?: (props: { focused: boolean; color: string }) => React.ReactNode;

/**
* Whether the tab icon should be visible. Defaults to `false`.
*/
tabBarShowIcon?: boolean;

/**
* Function that returns a React element to use as a badge for the tab.
*/
Expand All @@ -122,12 +128,6 @@ export type MaterialTopTabNavigationOptions = {
*/
tabBarIndicatorContainerStyle?: StyleProp<ViewStyle>;

/**
* Accessibility label for the tab button. This is read by the screen reader when the user taps the tab.
* It's recommended to set this if you don't have a label for the tab.
*/
tabBarAccessibilityLabel?: string;

/**
* ID to locate this tab button in tests.
*/
Expand All @@ -153,21 +153,6 @@ export type MaterialTopTabNavigationOptions = {
*/
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.
*/
Expand Down Expand Up @@ -204,6 +189,42 @@ export type MaterialTopTabNavigationOptions = {
* Style object for the the tab bar.
*/
tabBarStyle?: StyleProp<ViewStyle>;

/**
* Whether to enable swipe gestures when this screen is focused.
* Swipe gestures are enabled by default. Passing `false` will disable swipe gestures,
* but the user can still switch tabs by pressing the tab bar.
*/
swipeEnabled?: boolean;

/**
* Whether this screen should be lazily rendered. When this is set to `true`,
* the screen will be rendered as it comes into the viewport.
* By default all screens are rendered to provide a smoother swipe experience.
* But you might want to defer the rendering of screens out of the viewport until the user sees them.
* To enable lazy rendering for this screen, set `lazy` to `true`.
*
* When you enable `lazy`, the lazy loaded screens will usually take some time to render
* when they come into the viewport. You can use the `lazyPlaceholder` prop to customize
* what the user sees during this short period.
*/
lazy?: boolean;

/**
* When `lazy` is enabled, you can specify how many adjacent screens should be preloaded in advance with this prop.
* This value defaults to `0` which means lazy pages are loaded as they come into the viewport.
*/
lazyPreloadDistance?: number;

/**
* Function that returns a React element to render if this screen hasn't been rendered yet.
* The `lazy` option also needs to be enabled for this to work.
*
* This view is usually only shown for a split second. Keep it lightweight.
*
* By default, this renders `null`.
*/
lazyPlaceholder?: () => React.ReactNode;
};

export type MaterialTopTabDescriptor = Descriptor<
Expand All @@ -226,7 +247,10 @@ export type MaterialTopTabNavigationConfig = Omit<
| 'renderScene'
| 'renderTabBar'
| 'renderLazyPlaceholder'
| 'swipeEnabled'
| 'lazy'
| 'lazyPreloadDistance'
| 'lazyPlaceholder'
> & {
/**
* Function that returns a React element to display as the tab bar.
Expand Down
4 changes: 4 additions & 0 deletions packages/material-top-tabs/src/views/MaterialTopTabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export default function MaterialTopTabView({
});
};

const focusedOptions = descriptors[state.routes[state.index].key].options;

return (
<TabView<Route<string>>
{...rest}
Expand All @@ -57,6 +59,8 @@ export default function MaterialTopTabView({
descriptors[route.key].options.lazyPlaceholder?.() ?? null
}
lazy={({ route }) => descriptors[route.key].options.lazy === true}
lazyPreloadDistance={focusedOptions.lazyPreloadDistance}
swipeEnabled={focusedOptions.swipeEnabled}
onSwipeStart={() => navigation.emit({ type: 'swipeStart' })}
onSwipeEnd={() => navigation.emit({ type: 'swipeEnd' })}
sceneContainerStyle={[
Expand Down

0 comments on commit 5bfc396

Please sign in to comment.