Quick Intro to Storybook with React Native In A Simple Expo Application
Storybook and React Native will save you time and headaches
Overview
We start with a blank Expo application and show how to install and configure Storybook with React Native to run on your mobile device. We then add a new story which is a calendar component that allows you to pick a date from the calendar and return the response to the parent of the component
Source Code
// picker.stories.js
import { action } from "@storybook/addon-actions";
import { storiesOf } from "@storybook/react-native";
import React from "react";
import { CalendarPicker } from "../../../components/CalendarPicker";
import CenterView from "../CenterView";
storiesOf("Pickers", module)
.addDecorator((getStory) => <CenterView>{getStory()}</CenterView>)
.add("basic calendar", () => (
<CalendarPicker
onCancelDate={action("onCancelDate")}
onSaveDate={action("onSaveDate")}
/>
));
// components/CalendarPicker.js
import React, { useState } from "react";
import { Text, View, Button, StyleSheet, TouchableOpacity } from "react-native";
import { Agenda, Calendar, LocaleConfig } from "react-native-calendars";
LocaleConfig.locales["en"] = {
formatAccessibilityLabel: "dddd d 'of' MMMM 'of' yyyy",
monthNames: [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
],
monthNamesShort: [
"jan",
"feb",
"mar",
"apr",
"may",
"jun",
"jul",
"aug",
"sep",
"oct",
"nov",
"dec",
],
dayNames: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
],
dayNamesShort: ["S", "M", "T", "W", "T", "F", "S"],
// numbers: ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'] // number localization example
};
LocaleConfig.defaultLocale = "en";
export function CalendarPicker({ onSaveDate, onCancelDate }) {
const [selectedDate, setSelectedDate] = useState(null);
return (
<View style={styles.container}>
<Calendar
style={{
marginBottom: 10,
width: "100%",
}}
// Initially visible month. Default = Date()
// current={"2012-03-01"}
// Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
// minDate={"2012-05-10"}
// Maximum date that can be selected, dates after maxDate will be grayed out. Default = undefined
// maxDate={"2012-05-30"}
// Handler which gets executed on day press. Default = undefined
onDayPress={(day) => {
console.log("selected day", day);
setSelectedDate(day);
}}
// Handler which gets executed on day long press. Default = undefined
onDayLongPress={(day) => {
console.log("selected day", day);
}}
// Month format in calendar title. Formatting values: http://arshaw.com/xdate/#Formatting
// monthFormat={"yyyy MM"}
// Handler which gets executed when visible month changes in calendar. Default = undefined
onMonthChange={(month) => {
console.log("month changed", month);
}}
// Hide month navigation arrows. Default = false
// hideArrows={true}
// Replace default arrows with custom ones (direction can be 'left' or 'right')
// renderArrow={(direction) => <Arrow />}
// Do not show days of other months in month page. Default = false
hideExtraDays={true}
// If hideArrows = false and hideExtraDays = false do not switch month when tapping on greyed out
// day from another month that is visible in calendar page. Default = false
disableMonthChange={false}
// If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday
firstDay={1}
// Hide day names. Default = false
// hideDayNames={true}
// Show week numbers to the left. Default = false
showWeekNumbers={false}
// Handler which gets executed when press arrow icon left. It receive a callback can go back month
onPressArrowLeft={(subtractMonth) => subtractMonth()}
// Handler which gets executed when press arrow icon right. It receive a callback can go next month
onPressArrowRight={(addMonth) => addMonth()}
// Disable left arrow. Default = false
disableArrowLeft={false}
// Disable right arrow. Default = false
disableArrowRight={false}
// Disable all touch events for disabled days. can be override with disableTouchEvent in markedDates
disableAllTouchEventsForDisabledDays={true}
// Replace default month and year title with custom one. the function receive a date as parameter
// renderHeader={(date) => {
// /*Return JSX*/
// }}
// Enable the option to swipe between months. Default = false
enableSwipeMonths={true}
/>
<View
style={{
backgroundColor: "grey",
alignItems: "center",
paddingHorizontal: 20,
paddingVertical: 12,
borderRadius: 8,
}}
>
<View>
<Text
style={{ fontSize: "large", fontWeight: "bold", color: "white" }}
>
SELECTED DATE
</Text>
</View>
<View>
<Text
style={{ fontSize: "large", fontWeight: "bold", color: "white" }}
>
{selectedDate?.dateString}
</Text>
</View>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "space-evenly",
paddingHorizontal: 12,
}}
>
<TouchableOpacity
onPress={() => pickDocument()}
style={{
backgroundColor: "green",
padding: 8,
margin: 12,
alignItems: "center",
width: "45%",
borderRadius: 8,
}}
>
<Text
style={{
color: "white",
fontWeight: "bold",
textTransform: "uppercase",
textAlign: "center",
}}
onPress={() => onSaveDate(selectedDate)}
>
SAVE SELECTED DATE
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => onCancelDate(null)}
style={{
backgroundColor: "red",
padding: 8,
margin: 12,
alignItems: "center",
width: "45%",
borderRadius: 8,
alignContent: "center",
justifyContent: "center",
}}
>
<Text
style={{
color: "white",
fontWeight: "bold",
textTransform: "uppercase",
}}
>
CANCEL
</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
// borderColor: "grey",
// borderWidth: 1,
},
});
// storybook/stories/index.js
import "./Button/Button.stories";
import "./Welcome/Welcome.stories";
import "./Picker/Picker.stories"; //<== NEW