1 | # Storybook for React Native
|
2 |
|
3 | With Storybook for React Native you can design and develop individual React Native components without running your app.
|
4 |
|
5 | For more information visit: [storybook.js.org](https://storybook.js.org)
|
6 |
|
7 | > NOTE: `@storybook/react-native` and `@storybook/react-native-server` are now on a different release cycle from the Storybook Core packages (`@storybook/react`, `@storybook/vue`, etc.). The last stable version of `@storybook/react-native` is `5.3.25` and it should be used with `5.3` versions of Storybook Core.
|
8 |
|
9 | _To re-iterate storybook dependencies with a version 6.0 and higher are not supported by react native storybook yet._
|
10 |
|
11 | # Table of contents
|
12 |
|
13 | - 🚀 [Getting Started](#getting-started)
|
14 | - 📒 [Making stories](#making-stories)
|
15 | - 🔌 [On device Addons](#ondevice-addons)
|
16 | - 📱 [Other ways to render storybook](#other-ways-to-render-storybook)
|
17 | - 🔧 [getStorybookUI Options](#getstorybookui-options)
|
18 | - 🤝 [Contributing](#contributing)
|
19 |
|
20 | # Getting Started
|
21 |
|
22 | To get started run this command from within the root of your react native app:
|
23 |
|
24 | ```
|
25 | npx -p @storybook/cli sb init --type react_native
|
26 | ```
|
27 |
|
28 | You'll be prompted asking if you want to install @storybook/react-native-server, you can safely choose not to install this now since you can add it later and its not required.
|
29 |
|
30 | This command will setup most things for you, now you just need to add the following to your entrypoint (usually App.js or index.js).
|
31 |
|
32 | ```
|
33 | export {default} from "./storybook";
|
34 | ```
|
35 |
|
36 | The above steps use the storybook cli to install the most useful addons and creates a few example stories in a folder called `storybook`.
|
37 |
|
38 | All the config for storybook and the entrypoint also live in the `storybook` folder by default.
|
39 |
|
40 | If you prefer to set things up yourself you can follow the [manual setup](https://github.com/storybookjs/react-native/blob/master/app/react-native/docs/manual-setup.md)
|
41 |
|
42 | If you're struggling check out this [snack](https://snack.expo.io/@dannyhw/expo-storybook-example) with a working example
|
43 |
|
44 | # OndeviceUI and React native Server
|
45 |
|
46 | The react native storybook is designed to be flexible so that you can navigate all your stories and use addons within the device ui, you also have the option to use the web ui via `@storybook/react-native-server` if thats what you prefer.
|
47 |
|
48 | The UI that allows you to navigate stories on the device is what we will call the "OnDeviceUI". When referring to features specific to this UI this term is used to distinguish it from the server ui.
|
49 |
|
50 | # Making stories
|
51 |
|
52 | The simplest type of story could look something like this
|
53 |
|
54 | ```
|
55 |
|
56 | import React from 'react';
|
57 | import { storiesOf } from '@storybook/react-native';
|
58 |
|
59 | // I import the component I want to display here
|
60 | import CustomButton from './CustomButton';
|
61 |
|
62 | // here I define that I want to create stories with the label "Buttons",
|
63 | // this will be the name in the storybook navigation
|
64 |
|
65 | const buttonStories = storiesOf('Buttons', module);
|
66 |
|
67 | // then I add a story with the name default view, I can add multiple stories to button stories
|
68 | buttonStories.add('default view', () => (<CustomButton onPress={() => null} />));
|
69 | ```
|
70 |
|
71 | You can then include addons such as action and knobs to make it more interactive.
|
72 |
|
73 | # Ondevice Addons
|
74 |
|
75 | The cli will install some basic addons for you such as knobs and actions.
|
76 | Ondevice addons are addons that can render with the device ui that you see on the phone.
|
77 |
|
78 | Currently the addons available are:
|
79 |
|
80 | - @storybook/addon-ondevice-knobs: adjust your components props in realtime
|
81 | - @storybook/addon-ondevice-actions: mock onPress calls with actions that will log information in the actions tab
|
82 | - @storybook/addon-ondevice-notes: Add some markdown to your stories to help document their usage
|
83 | - @storybook/addon-ondevice-backgrounds: change the background of storybook to compare the look of your component against different backgrounds
|
84 |
|
85 | Add each one you want to use to the rn-addons.js file in the `storybook` folder:
|
86 |
|
87 | ```
|
88 | import '@storybook/addon-ondevice-actions/register';
|
89 | ```
|
90 |
|
91 | Make sure to import the rn-addons.js file in the storybook entrypoint (index.js in the storybook folder by default):
|
92 |
|
93 | ```
|
94 | import './rn-addons';
|
95 | ```
|
96 |
|
97 | ### Using the addons in your story
|
98 |
|
99 | Based on the previous example heres how you could extend it to use addons.
|
100 |
|
101 | ```
|
102 | import React from 'react';
|
103 | import { storiesOf } from '@storybook/react-native';
|
104 | import CustomButton from './CustomButton';
|
105 | import { View } from 'react-native';
|
106 |
|
107 | // the action function has one argument which is the name of the action,
|
108 | // this will be displayed in the actions tab in the addons panel
|
109 | // action("name here")
|
110 | import { action } from '@storybook/addon-actions';
|
111 |
|
112 | // the boolean knob renders a switch which lets you toggle a value between true or false
|
113 | // you call it like boolean("name here", default_value)
|
114 | import { boolean, withKnobs } from '@storybook/addon-knobs';
|
115 |
|
116 | const buttonStories = storiesOf('CustomButton', module);
|
117 |
|
118 | // lets storybook know to show the knobs addon for this story
|
119 | buttonStories.addDecorator(withKnobs);
|
120 |
|
121 | // I use to boolean knob to set the disabled prop based on the knob state
|
122 | // I use the action function to log every time the button gets called
|
123 | buttonStories.add('default view', () => (
|
124 | <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
125 | <CustomButton onPress={action('Button Press!')} disabled={boolean('Disabled', false)} />
|
126 | </View>
|
127 | ));
|
128 | ```
|
129 |
|
130 | # Other ways to render storybook
|
131 |
|
132 | In the getting started guide we suggest that you override you change the default export to be the storybook UI, this might not be what you want depending on how you are using storybook.
|
133 |
|
134 | There are a few options on how you can make the storybook render in your app so it's up to you to decide which works best for your project.
|
135 |
|
136 | ## Run storybook as a separate app/component library
|
137 |
|
138 | Using the approach from the getting started setup you can make an app that just displays your storybook and then you could use this app to share your component library. Then you can export all your components from somewhere within the project and use the project as a component library/package.
|
139 |
|
140 | ## Optionally run storybook or your app
|
141 |
|
142 | You could do something like this if you want to run storybook in dev mode and your app in release mode.
|
143 |
|
144 | ```js
|
145 | import StorybookUI from './storybook';
|
146 |
|
147 | import App from './app';
|
148 |
|
149 | module.exports = __DEV__ ? StorybookUI : App;
|
150 | ```
|
151 |
|
152 | Or you could use some kind of setting/environment variable to define what renders.
|
153 |
|
154 | ## React Native Navigation, or other custom approaches
|
155 |
|
156 | `StorybookUI` is a RN `View` component that can be embedded anywhere in your RN application, e.g. on a tab or within an admin screen.
|
157 |
|
158 | You could also create a separate app just for storybook that also works as a package for your visual components.
|
159 |
|
160 | # Storybook server (optional)
|
161 |
|
162 | Storybook server is used to control the component visible on the device via a web ui. This is useful to control multiple devices at once and compare them at the same time.
|
163 |
|
164 | Install the package
|
165 |
|
166 | yarn `yarn add @storybook/react-native-server`
|
167 |
|
168 | npm `npm i --save @storybook/react-native-server`
|
169 |
|
170 | To run the server you can use `yarn start-storybook`
|
171 | or add a script to your package.json like
|
172 |
|
173 | ```
|
174 | "storybook": "start-storybook"
|
175 | ```
|
176 |
|
177 | _You can change "storybook" to any name you like._
|
178 |
|
179 | This will open the server web client, you will need to open storybook on the device for the stories to appear in the sidebar.
|
180 |
|
181 | To enable addons for react native server add a folder `storybook/` in the root of the project with a addons.js file inside. The server will detect this file and import it. The file should contain the addon imports similar to the rn-addons.js file but using the regular storybook (for web) addons. For example:
|
182 |
|
183 | ```
|
184 | // storybook/addons.js
|
185 | require('@storybook/addon-knobs/register');
|
186 | require('@storybook/addon-actions/register');
|
187 | ```
|
188 |
|
189 | If you get the error `Can't resolve 'babel-loader'` install babel-loader from npm and it should fix it.
|
190 |
|
191 | ### Server cli options
|
192 |
|
193 | ```
|
194 | -h, --host <host>
|
195 | host to listen on
|
196 | -p, --port <port>
|
197 | port to listen on
|
198 | --https
|
199 | whether server is running on https
|
200 | -c, --config-dir [dir-name]
|
201 | storybook config directory
|
202 | -e, --environment [environment]
|
203 | DEVELOPMENT/PRODUCTION environment for webpack
|
204 | -i, --manual-id
|
205 | allow multiple users to work with same storybook
|
206 | --smoke-test
|
207 | Exit after successful start
|
208 | ```
|
209 |
|
210 | # getStorybookUI Options
|
211 |
|
212 | You can pass these parameters to getStorybookUI call in your storybook entry point:
|
213 |
|
214 | ```
|
215 | {
|
216 | onDeviceUI: Boolean (true)
|
217 | -- display navigator and addons on the device
|
218 | disableWebsockets: Boolean (false)
|
219 | -- allows to display stories without running storybook server. Should be used with onDeviceUI
|
220 | secured: Boolean (false)
|
221 | -- use wss/https instead of ws/http
|
222 | host: String (NativeModules.SourceCode.scriptURL)
|
223 | -- host to use
|
224 | port: Number (7007)
|
225 | -- port to use
|
226 | query: String ("")
|
227 | -- additional query string to pass to websockets
|
228 | isUIHidden: Boolean (false)
|
229 | -- should the ui be closed initially.
|
230 | tabOpen: Number (0)
|
231 | -- which tab should be open. -1 Navigator, 0 Preview, 1 Addons
|
232 | initialSelection: Object (null)
|
233 | -- initialize storybook with a specific story. In case a valid object is passed, it will take precedence over `shouldPersistSelection. ex: `{ kind: 'Knobs', story: 'with knobs' }`
|
234 | shouldPersistSelection: Boolean (true)
|
235 | -- initialize storybook with the last selected story.
|
236 | shouldDisableKeyboardAvoidingView: Boolean (false)
|
237 | -- Disable KeyboardAvoidingView wrapping Storybook's view
|
238 | keyboardAvoidingViewVerticalOffset: Number (0)
|
239 | -- With shouldDisableKeyboardAvoidingView=true, this will set the keyboardverticaloffset (https://facebook.github.io/react-native/docs/keyboardavoidingview#keyboardverticaloffset) value for KeyboardAvoidingView wrapping Storybook's view
|
240 | }
|
241 | ```
|
242 |
|
243 | # Contributing
|
244 |
|
245 | We welcome contributions to Storybook!
|
246 |
|
247 | - 📥 Pull requests and 🌟 Stars are always welcome.
|
248 | - Read our [contributing guide](https://github.com/storybookjs/react-native/blob/master/CONTRIBUTING.md) to get started,
|
249 | or find us on [Discord](https://discord.gg/sMFvFsG) and look for the react-native channel.
|
250 |
|
251 | Looking for a first issue to tackle?
|
252 |
|
253 | - We tag issues with [Good First Issue](https://github.com/storybookjs/react-native/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) when we think they are well suited for people who are new to the codebase or OSS in general.
|
254 | - [Talk to us](https://discord.gg/sMFvFsG), we'll find something to suits your skills and learning interest.
|