diff --git a/packages/react-navigation/docs/api/navigators/DrawerNavigator.md b/packages/react-navigation/docs/api/navigators/DrawerNavigator.md index bd759db9..a524b3f4 100644 --- a/packages/react-navigation/docs/api/navigators/DrawerNavigator.md +++ b/packages/react-navigation/docs/api/navigators/DrawerNavigator.md @@ -94,21 +94,6 @@ The route configs object is a mapping from route name to a route config, which t - `useNativeAnimations` - Enable native animations. Default is `true`. - `drawerBackgroundColor` - Use the Drawer background for some color. The Default is `white`. -#### Example: - -Default the `DrawerView` isn't scrollable. -To achieve a scrollable `View`, you have to use the `contentComponent` to customize the container, -as you can see in the example below. - -```js -{ - drawerWidth: 200, - drawerPosition: 'right', - contentComponent: props => , - drawerBackgroundColor: 'transparent' -} -``` - Several options get passed to the underlying router to modify navigation logic: - `initialRouteName` - The routeName for the initial route. @@ -118,15 +103,17 @@ Several options get passed to the underlying router to modify navigation logic: ### Providing a custom `contentComponent` -You can easily override the default component used by `react-navigation`: +The default component for the drawer is scrollable and only contains links for the routes in the RouteConfig. You can easily override the default component to add a header, footer, or other content to the drawer. By default the drawer is scrollable and supports iPhone X safe area. If you customize the content, be sure to wrap the content in a SafeAreaView: ```js -import { DrawerItems } from 'react-navigation'; +import { DrawerItems, SafeAreaView } from 'react-navigation'; const CustomDrawerContentComponent = (props) => ( - - - + + + + + ); const styles = StyleSheet.create({ @@ -145,7 +132,6 @@ const styles = StyleSheet.create({ - `inactiveTintColor` - label and icon color of the inactive label - `inactiveBackgroundColor` - background color of the inactive label - `onItemPress(route)` - function to be invoked when an item is pressed -- `itemsContainerForceInset` - override default forceInset on the SafeAreaView that wraps the items container component - `itemsContainerStyle` - style object for the content section - `itemStyle` - style object for the single item, which can contain an Icon and/or a Label - `labelStyle` - style object to overwrite `Text` style inside content section, when your label is a string diff --git a/packages/react-navigation/src/navigators/DrawerNavigator.js b/packages/react-navigation/src/navigators/DrawerNavigator.js index 42efc57d..6b597226 100644 --- a/packages/react-navigation/src/navigators/DrawerNavigator.js +++ b/packages/react-navigation/src/navigators/DrawerNavigator.js @@ -1,7 +1,7 @@ /* @flow */ import React from 'react'; -import { Dimensions, Platform } from 'react-native'; +import { Dimensions, Platform, ScrollView } from 'react-native'; import createNavigator from './createNavigator'; import createNavigationContainer from '../createNavigationContainer'; @@ -9,6 +9,7 @@ import TabRouter from '../routers/TabRouter'; import DrawerScreen from '../views/Drawer/DrawerScreen'; import DrawerView from '../views/Drawer/DrawerView'; import DrawerItems from '../views/Drawer/DrawerNavigatorItems'; +import SafeAreaView from '../views/SafeAreaView'; import NavigatorTypes from './NavigatorTypes'; @@ -25,13 +26,21 @@ export type DrawerNavigatorConfig = { const { height, width } = Dimensions.get('window'); +const defaultContentComponent = (props: *) => ( + + + + + +); + const DefaultDrawerConfig = { /* * Default drawer width is screen width - header width * https://material.io/guidelines/patterns/navigation-drawer.html */ drawerWidth: Math.min(height, width) - (Platform.OS === 'android' ? 56 : 64), - contentComponent: DrawerItems, + contentComponent: defaultContentComponent, drawerPosition: 'left', drawerBackgroundColor: 'white', useNativeAnimations: true, diff --git a/packages/react-navigation/src/navigators/__tests__/__snapshots__/DrawerNavigator-test.js.snap b/packages/react-navigation/src/navigators/__tests__/__snapshots__/DrawerNavigator-test.js.snap index 34462de9..9b39e994 100644 --- a/packages/react-navigation/src/navigators/__tests__/__snapshots__/DrawerNavigator-test.js.snap +++ b/packages/react-navigation/src/navigators/__tests__/__snapshots__/DrawerNavigator-test.js.snap @@ -91,99 +91,146 @@ exports[`DrawerNavigator renders successfully 1`] = ` ] } > - - - - Welcome anonymous - + + + Welcome anonymous + + + - - + + diff --git a/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js b/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js index 3ed4427e..0fbcf7e3 100644 --- a/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js +++ b/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js @@ -31,6 +31,7 @@ type Props = { itemStyle?: ViewStyleProp, labelStyle?: TextStyleProp, iconContainerStyle?: ViewStyleProp, + drawerPosition: 'left' | 'right', }; /** @@ -47,61 +48,63 @@ const DrawerNavigatorItems = ({ getLabel, renderIcon, onItemPress, - itemsContainerForceInset = { horizontal: 'never', top: 'always' }, itemsContainerStyle, itemStyle, labelStyle, iconContainerStyle, + drawerPosition, }: Props) => ( - - - {items.map((route: NavigationRoute, index: number) => { - const focused = activeItemKey === route.key; - const color = focused ? activeTintColor : inactiveTintColor; - const backgroundColor = focused - ? activeBackgroundColor - : inactiveBackgroundColor; - const scene = { route, index, focused, tintColor: color }; - const icon = renderIcon(scene); - const label = getLabel(scene); - return ( - { - onItemPress({ route, focused }); + + {items.map((route: NavigationRoute, index: number) => { + const focused = activeItemKey === route.key; + const color = focused ? activeTintColor : inactiveTintColor; + const backgroundColor = focused + ? activeBackgroundColor + : inactiveBackgroundColor; + const scene = { route, index, focused, tintColor: color }; + const icon = renderIcon(scene); + const label = getLabel(scene); + return ( + { + onItemPress({ route, focused }); + }} + delayPressIn={0} + > + - - - {icon ? ( - - {icon} - - ) : null} - {typeof label === 'string' ? ( - - {label} - - ) : ( - label - )} - - - - ); - })} - - + + {icon ? ( + + {icon} + + ) : null} + {typeof label === 'string' ? ( + + {label} + + ) : ( + label + )} + + + + ); + })} + ); /* Material design specs - https://material.io/guidelines/patterns/navigation-drawer.html#navigation-drawer-specs */ diff --git a/packages/react-navigation/src/views/Drawer/DrawerSidebar.js b/packages/react-navigation/src/views/Drawer/DrawerSidebar.js index a2d3d898..1a04114c 100644 --- a/packages/react-navigation/src/views/Drawer/DrawerSidebar.js +++ b/packages/react-navigation/src/views/Drawer/DrawerSidebar.js @@ -7,6 +7,8 @@ import withCachedChildNavigation from '../../withCachedChildNavigation'; import NavigationActions from '../../NavigationActions'; import invariant from '../../utils/invariant'; +import SafeAreaView from '../SafeAreaView'; + import type { NavigationScreenProp, NavigationRoute, @@ -34,6 +36,7 @@ type Props = { contentOptions?: {}, screenProps?: {}, style?: ViewStyleProp, + drawerPosition?: 'left' | 'right', }; /** @@ -123,6 +126,7 @@ class DrawerSidebar extends React.PureComponent { renderIcon={this._renderIcon} onItemPress={this._onItemPress} router={this.props.router} + drawerPosition={this.props.drawerPosition} /> ); diff --git a/packages/react-navigation/src/views/Drawer/DrawerView.js b/packages/react-navigation/src/views/Drawer/DrawerView.js index d7597c51..732324c1 100644 --- a/packages/react-navigation/src/views/Drawer/DrawerView.js +++ b/packages/react-navigation/src/views/Drawer/DrawerView.js @@ -134,6 +134,7 @@ export default class DrawerView extends React.PureComponent< router={this.props.router} contentComponent={this.props.contentComponent} contentOptions={this.props.contentOptions} + drawerPosition={this.props.drawerPosition} style={this.props.style} /> );