React Native Propel Kit

React Native Propel Kit

  • Quick Start
  • Components
  • Github
  • v0.8.6

›Components

Introduction

  • Quick Start

Components

  • ActionSheetProvider
  • BackdropProvider
  • ModalDialog
  • Select
  • DatePicker
  • TimePicker
  • DateTimePicker
  • MonthPicker
  • YearPicker
  • Picker

Recipes

  • Customizing styles

ActionSheet Provider

<ActionSheetProvider /> is a Context Provider that enables the usage of a cross-platform <ActionSheet /> component anywhere in your application.

  • On iOS, defaults to the native ActionSheetIOS, but you can opt-in for a software pixel perfect implementation if you need more customization.

  • On android, uses a custom software implementation that aims to blend nicely with the OS interface.

It is built upon the <ModalDialog /> component.

Preview

iOSAndroid

Usage

Required setup

As this component leverages a backdrop, you also need to wrap your application with a <BackdropProvider /> component. You usually want to wrap it as high as possible in your tree so that the backdrop properly covers the whole screen.

// App.jsx

import React from 'react';
import {ActionSheetProvider, BackdropProvider} from 'react-native-propel-kit';

const App = () => {
  return (
    <BackdropProvider>
      <ActionSheetProvider>
        <RootNavigator />
      </ActionSheetProvider>
    </BackdropProvider>
  );
};

export default App;

Usage with context

Easiest way to use the backdrop in a component is to use react useContext hook

// MyComponent.jsx

import React from 'react';
import {Button} from 'react-native';
import {ActionSheetContext} from 'react-native-propel-kit';

const MyComponent = () => {
  const actionSheet = useContext(ActionSheetContext);
  const handlePress = useCallback(() => {
    actionSheet.showWithOptions(
      {
        title: 'Are you sure?',
        message: 'Please confirm the removal',
        options: ['Cancel', 'Remove'],
        destructiveButtonIndex: 1,
        cancelButtonIndex: 0
      },
      buttonIndex => {
        console.warn('onButtonPress', {buttonIndex});
      }
    );
  }, [actionSheet]);
  return <Button onPress={handlePress} title="Show ActionSheet" />;
};

export default MyComponent;

Usage with consumer

An alternative way to use the backdrop is to use the <ActionSheetContext.Consumer /> component as a higher order component providing the actionSheet context API.

// MyComponent.jsx

import React from 'react';
import {Button} from 'react-native';
import {ActionSheetContext} from 'react-native-propel-kit';

const MyComponent = () => {
  return (
    <ActionSheetContext.Consumer>
      {actionSheet => (
        <Button
          onPress={() => {
            actionSheet.showWithOptions(
              {
                title: 'Are you sure?',
                message: 'Please confirm the removal',
                options: ['Cancel', 'Remove'],
                destructiveButtonIndex: 1,
                cancelButtonIndex: 0
              },
              buttonIndex => {
                console.warn('onButtonPress', {buttonIndex});
              }
            );
          }}
          title="Open"
        />
      )}
    </ActionSheetContext.Consumer>
  );
};

export default MyComponent;

Props

ActionSheet

export type Props = Pick<ScrollViewProps, 'scrollEnabled'> &
  Omit<ModalDialogProps, 'onConfirm' | 'confirmTitle' | 'confirmStyle'> &
  ActionSheetIOSOptions & {
    defaultStyles?: typeof defaultStyles;
    optionStyle?: StyleProp<TextStyle>;
    lastOptionExtraStyle?: StyleProp<TextStyle>;
    destructiveButtonColor?: string;
    onButtonPress: (buttonIndex: number) => void;
    onCancel: () => void;
  };

Defaults

export const defaultProps = {
  backgroundColor: 'white',
  cancelTitle: 'Cancel',
  destructiveButtonColor: Platform.select({
    ios: '#ff3b30', // iOS.systemRed (@see https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/)
    android: '#f44336' // android.red500 (@see https://material.io/design/color/the-color-system.html)
  })
};

ActionSheetProvider

export type Props = Omit<ActionSheetProps, 'options'> & {
  native?: boolean;
};

Styles

export const defaultStyles = {
  modal: Platform.select<ViewStyle>({
    ios: {flex: 1, justifyContent: 'flex-end'},
    android: {flex: 1, justifyContent: 'center'}
  }),
  container: Platform.select<ViewStyle>({
    ios: {margin: 8, maxHeight: WINDOW_HEIGHT - 8 * 2},
    android: {
      flexDirection: 'column',
      alignItems: 'stretch',
      // marginHorizontal: 82, // timepicker/spinner
      margin: 24,
      maxHeight: WINDOW_HEIGHT - 24 * 2,
      elevation: 4
    }
  }),
  header: Platform.select<ViewStyle>({
    ios: {
      alignItems: 'center',
      padding: 16,
      borderTopLeftRadius: 12,
      borderTopRightRadius: 12,
      opacity: IOS_OPACITY
    },
    android: {alignItems: 'flex-start', paddingVertical: 24, paddingHorizontal: 32}
  }),
  body: Platform.select<ViewStyle>({
    ios: {
      flexShrink: 1,
      flexDirection: 'column',
      backgroundColor: 'transparent',
      opacity: IOS_OPACITY,
      borderBottomStartRadius: 12,
      borderBottomEndRadius: 12
    },
    android: {
      flexShrink: 1,
      flexDirection: 'column',
      backgroundColor: 'transparent'
    }
  }),
  footer: Platform.select<TextStyle>({
    ios: {}, // @NOTE we don't have a footer on iOS
    android: {
      flexDirection: 'row',
      justifyContent: 'flex-end',
      borderBottomLeftRadius: 2,
      borderBottomRightRadius: 2,
      padding: 8
    }
  }),
  title: Platform.select<TextStyle>({
    ios: {paddingBottom: 12, fontSize: 14, fontWeight: '500', textAlign: 'center', color: '#888'},
    android: {
      paddingBottom: 12,
      fontSize: 20,
      fontWeight: '500',
      textAlign: 'left',
      color: '#333'
    }
  }),
  message: Platform.select<TextStyle>({
    ios: {paddingBottom: 12, fontSize: 13, fontWeight: '400', textAlign: 'center', color: '#888'},
    android: {paddingBottom: 12, fontSize: 18, fontWeight: '400', color: '#666'}
  }),
  cancel: Platform.select<TextStyle>({
    ios: {marginTop: 8, borderRadius: 12, fontWeight: '600'},
    android: {}
  }),
  confirm: Platform.select<TextStyle>({
    ios: {}, // @NOTE we don't have a confirm on iOS
    android: {}
  }),
  option: Platform.select<TextStyle>({
    ios: {
      marginTop: StyleSheet.hairlineWidth
    },
    android: {
      marginTop: StyleSheet.hairlineWidth
    }
  }),
  lastOptionExtra: Platform.select<TextStyle>({
    ios: {
      borderBottomLeftRadius: 12,
      borderBottomRightRadius: 12
    },
    android: {
      marginBottom: StyleSheet.hairlineWidth
    }
  })
};
Last updated on 9/25/2019
← Quick StartBackdropProvider →
  • Preview
  • Usage
    • Required setup
    • Usage with context
    • Usage with consumer
  • Props
    • ActionSheet
    • ActionSheetProvider
  • Styles
React Native Propel Kit
Docs
Getting Started (or other categories)Guides (or other categories)API Reference (or other categories)
Community
User ShowcaseStack OverflowProject ChatTwitter
More
BlogGitHubStar
Facebook Open Source
Copyright © 2019 Olivier Louvignes