@storybook/react-native 10.0.0-rc.1 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -60,9 +60,8 @@ interface WithStorybookOptions {
60
60
  * @param options.useJs - Whether to use JavaScript files for Storybook configuration instead of TypeScript.
61
61
  * When true, generates storybook.requires.js instead of storybook.requires.ts.
62
62
  * Defaults to false.
63
- * @param options.removeStorybook - If enabled is false and this is true, attempts to remove
64
- * storybook modules from the JavaScript bundle to reduce bundle size.
65
- * Defaults to false.
63
+ * @param options.enabled - If false, attempts to remove storybook modules from the JavaScript
64
+ * bundle to reduce bundle size. Defaults to true.
66
65
  * @param options.docTools - Whether to include doc tools in the storybook.requires file.
67
66
  * Doc tools provide additional documentation features. Defaults to true.
68
67
  * @param options.liteMode - Whether to use lite mode for the storybook. In lite mode, the default
@@ -107,7 +106,7 @@ interface WithStorybookOptions {
107
106
  *
108
107
  * const config = getDefaultConfig(__dirname);
109
108
  * module.exports = withStorybook(config, {
110
- * removeStorybook: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED !== "true",
109
+ * enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === "true",
111
110
  * });
112
111
  * ```
113
112
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native",
3
- "version": "10.0.0-rc.1",
3
+ "version": "10.0.0",
4
4
  "description": "A better way to develop React Native Components for your app",
5
5
  "keywords": [
6
6
  "react",
@@ -49,10 +49,10 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@storybook/global": "^5.0.0",
52
- "@storybook/react": "10.0.0-rc.1",
53
- "@storybook/react-native-theming": "^10.0.0-rc.1",
54
- "@storybook/react-native-ui": "^10.0.0-rc.1",
55
- "@storybook/react-native-ui-common": "^10.0.0-rc.1",
52
+ "@storybook/react": "^10.0.0",
53
+ "@storybook/react-native-theming": "^10.0.0",
54
+ "@storybook/react-native-ui": "^10.0.0",
55
+ "@storybook/react-native-ui-common": "^10.0.0",
56
56
  "commander": "^8.2.0",
57
57
  "dedent": "^1.5.1",
58
58
  "deepmerge": "^4.3.0",
@@ -74,7 +74,7 @@
74
74
  "jotai": "^2.6.2",
75
75
  "react": "19.1.0",
76
76
  "react-native": "0.81.4",
77
- "storybook": "10.0.0-rc.1",
77
+ "storybook": "^10.0.0",
78
78
  "tsup": "^8.5.0",
79
79
  "typescript": "~5.9.2",
80
80
  "universal-test-renderer": "^0.6.0"
@@ -86,7 +86,7 @@
86
86
  "react-native-gesture-handler": ">=2",
87
87
  "react-native-reanimated": ">=2",
88
88
  "react-native-safe-area-context": "*",
89
- "storybook": ">=10 || 10.0.0-beta.0 || ^10"
89
+ "storybook": ">=10 || ^10"
90
90
  },
91
91
  "peerDependenciesMeta": {
92
92
  "@gorhom/bottom-sheet": {
@@ -108,5 +108,5 @@
108
108
  "publishConfig": {
109
109
  "access": "public"
110
110
  },
111
- "gitHead": "b1b99bb72fa5713564390e65d556f1ec47c8c7b3"
111
+ "gitHead": "f2af5e230aac4cd858f2d73909868ae4952eb1c1"
112
112
  }
package/readme.md CHANGED
@@ -1,13 +1,17 @@
1
1
  # Storybook for React Native
2
2
 
3
- > This readme is for v9, for v8 docs see the [v8.6 docs](https://github.com/storybookjs/react-native/tree/v8.6.0-stable).
3
+ A new docs site is being built for Storybook for React Native, you can find it at https://storybookjs.github.io/react-native/docs/intro/.
4
+
5
+ > [!IMPORTANT]
6
+ > This readme is for v10, for v9 docs see the [v9.1 docs](https://github.com/storybookjs/react-native/tree/v9.1.4).
4
7
 
5
8
  With Storybook for React Native you can design and develop individual React Native components without running your app.
6
9
 
7
- If you are migrating from 8 to 9 you can find the migration guide [here](https://github.com/storybookjs/react-native/blob/next/MIGRATION.md#from-version-8-to-9)
10
+ If you are migrating from 9 to 10 you can find the migration guide [here](https://github.com/storybookjs/react-native/blob/next/MIGRATION.md#from-version-9-to-10)
8
11
 
9
12
  For more information about storybook visit: [storybook.js.org](https://storybook.js.org)
10
13
 
14
+ > [!NOTE]
11
15
  > Make sure you align your storybook dependencies to the same major version or you will see broken behaviour.
12
16
 
13
17
  ![picture of storybook](https://github.com/user-attachments/assets/cf98766d-8b90-44ab-b718-94ab16e63205)
@@ -79,23 +83,23 @@ Then wrap your config in the withStorybook function as seen below.
79
83
 
80
84
  ```js
81
85
  // metro.config.js
82
- const path = require('path');
83
86
  const { getDefaultConfig } = require('expo/metro-config');
84
- const withStorybook = require('@storybook/react-native/metro/withStorybook');
87
+ const { withStorybook } = require('@storybook/react-native/metro/withStorybook');
85
88
 
86
- /** @type {import('expo/metro-config').MetroConfig} */
87
89
  const config = getDefaultConfig(__dirname);
88
90
 
91
+ // For basic usage with all defaults, this is all you need
92
+ module.exports = withStorybook(config);
93
+
94
+ // Or customize the options
89
95
  module.exports = withStorybook(config, {
90
- // Set to false to remove storybook specific options
91
- // you can also use a env variable to set this
92
- enabled: true,
93
- // Path to your storybook config
94
- configPath: path.resolve(__dirname, './.rnstorybook'),
95
- // note that this is the default so you can the config path blank if you use .rnstorybook
96
+ // When false, removes Storybook from bundle (useful for production)
97
+ enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true',
96
98
 
97
- // Optional websockets configuration
98
- // Starts a websocket server on the specified port and host on metro start
99
+ // Path to your storybook config (default: './.rnstorybook')
100
+ configPath: './.rnstorybook',
101
+
102
+ // Optional websockets configuration for syncing between devices
99
103
  // websockets: {
100
104
  // port: 7007,
101
105
  // host: 'localhost',
@@ -107,8 +111,8 @@ module.exports = withStorybook(config, {
107
111
 
108
112
  ```js
109
113
  const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
110
- const path = require('path');
111
- const withStorybook = require('@storybook/react-native/metro/withStorybook');
114
+ const { withStorybook } = require('@storybook/react-native/metro/withStorybook');
115
+
112
116
  const defaultConfig = getDefaultConfig(__dirname);
113
117
 
114
118
  /**
@@ -122,15 +126,19 @@ const config = {};
122
126
 
123
127
  const finalConfig = mergeConfig(defaultConfig, config);
124
128
 
129
+ // For basic usage with all defaults
130
+ module.exports = withStorybook(finalConfig);
131
+
132
+ // Or customize the options
125
133
  module.exports = withStorybook(finalConfig, {
126
- // Set to false to remove storybook specific options
127
- // you can also use a env variable to set this
128
- enabled: true,
129
- // Path to your storybook config
134
+ // When false, removes Storybook from bundle (useful for production)
135
+ enabled: process.env.STORYBOOK_ENABLED === 'true',
136
+
137
+ // Path to your storybook config (default: './.rnstorybook')
130
138
  configPath: path.resolve(__dirname, './.rnstorybook'),
131
139
  // note that this is the default so you can the config path blank if you use .rnstorybook
132
140
 
133
- // Optional websockets configuration
141
+ // Optional websockets configuration for syncing between devices
134
142
  // Starts a websocket server on the specified port and host on metro start
135
143
  // websockets: {
136
144
  // port: 7007,
@@ -148,12 +156,45 @@ Make sure you have `react-native-reanimated` in your project and the plugin setu
148
156
  plugins: ['react-native-reanimated/plugin'],
149
157
  ```
150
158
 
159
+ ## Expo router specific setup
160
+
161
+ ```bash
162
+ npm create storybook@latest
163
+ ```
164
+
165
+ choose recommended and then native
166
+
167
+ ```bash
168
+ npx expo@latest customize metro.config.js
169
+ ```
170
+
171
+ copy the metro config
172
+
173
+ ```js
174
+ const withStorybook = require('@storybook/react-native/metro/withStorybook');
175
+ module.exports = withStorybook(config);
176
+ ```
177
+
178
+ add storybook screen to app
179
+
180
+ create `app/storybook.tsx`
181
+
182
+ ```tsx
183
+ export { default } from '../.rnstorybook';
184
+ ```
185
+
186
+ Then add a way to navigate to your storybook route and I recommend disabling the header for the storybook route.
187
+
188
+ Heres a video showing the same setup:
189
+
190
+ https://www.youtube.com/watch?v=egBqrYg0AIg
191
+
151
192
  ## Writing stories
152
193
 
153
194
  In storybook we use a syntax called CSF that looks like this:
154
195
 
155
196
  ```tsx
156
- import type { Meta, StoryObj } from '@storybook/react';
197
+ import type { Meta, StoryObj } from '@storybook/react-native';
157
198
  import { MyButton } from './Button';
158
199
 
159
200
  const meta = {
@@ -222,7 +263,7 @@ For global decorators and parameters, you can add them to `preview.tsx` inside y
222
263
 
223
264
  ```tsx
224
265
  // .rnstorybook/preview.tsx
225
- import type { Preview } from '@storybook/react';
266
+ import type {
226
267
  import { withBackgrounds } from '@storybook/addon-ondevice-backgrounds';
227
268
 
228
269
  const preview: Preview = {
@@ -291,13 +332,52 @@ For details of each ondevice addon you can see the readme:
291
332
 
292
333
  ## Hide/Show storybook
293
334
 
294
- Storybook on react native is a normal React Native component that can be used or hidden anywhere in your RN application based on your own logic.
335
+ In v10, you have flexible options for integrating Storybook into your app:
295
336
 
296
- You can also create a separate app just for storybook that also works as a package for your visual components.
297
- Some have opted to toggle the storybook component by using a custom option in the react native developer menu.
337
+ ### Option 1: Direct export (simplest)
298
338
 
299
- - [Heres an approach for react native cli](https://dev.to/dannyhw/multiple-entry-points-for-react-native-storybook-4dkp)
300
- - [Heres an article about how you can do it in expo](https://dev.to/dannyhw/how-to-swap-between-react-native-storybook-and-your-app-p3o)
339
+ Just export Storybook directly. Control inclusion via the metro config `enabled` flag:
340
+
341
+ ```tsx
342
+ // App.tsx
343
+ export { default } from './.rnstorybook';
344
+ ```
345
+
346
+ ```js
347
+ // metro.config.js
348
+ module.exports = withStorybook(config, {
349
+ enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true',
350
+ });
351
+ ```
352
+
353
+ When `enabled: false`, Metro automatically removes Storybook from your bundle.
354
+
355
+ ### Option 2: Conditional rendering
356
+
357
+ If you want to switch between your app and Storybook at runtime:
358
+
359
+ ```tsx
360
+ // App.tsx
361
+ import StorybookUI from './.rnstorybook';
362
+ import { MyApp } from './MyApp';
363
+
364
+ const isStorybook = process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true';
365
+
366
+ export default function App() {
367
+ return isStorybook ? <StorybookUI /> : <MyApp />;
368
+ }
369
+ ```
370
+
371
+ ### Option 3: Expo Router (recommended for Expo)
372
+
373
+ Create a dedicated route for Storybook:
374
+
375
+ ```tsx
376
+ // app/storybook.tsx
377
+ export { default } from '../.rnstorybook';
378
+ ```
379
+
380
+ Then navigate to `/storybook` in your app to view stories.
301
381
 
302
382
  ## withStorybook wrapper
303
383
 
@@ -322,7 +402,9 @@ module.exports = withStorybook(defaultConfig, {
322
402
 
323
403
  Type: `boolean`, default: `true`
324
404
 
325
- Determines whether the options specified are applied to the Metro config. This can be useful for project setups that use Metro both with and without Storybook and need to conditionally apply the options. In this example, it is made conditional using an environment variable:
405
+ Controls whether Storybook is included in your app bundle. When `true`, enables Storybook metro configuration and generates the `storybook.requires` file. When `false`, removes all Storybook code from the bundle by replacing imports with empty modules.
406
+
407
+ This is useful for conditionally including Storybook in development but excluding it from production builds:
326
408
 
327
409
  ```js
328
410
  // metro.config.js
@@ -332,18 +414,11 @@ const withStorybook = require('@storybook/react-native/metro/withStorybook');
332
414
  const defaultConfig = getDefaultConfig(__dirname);
333
415
 
334
416
  module.exports = withStorybook(defaultConfig, {
335
- enabled: process.env.WITH_STORYBOOK,
417
+ enabled: process.env.STORYBOOK_ENABLED === 'true',
336
418
  // ... other options
337
419
  });
338
420
  ```
339
421
 
340
- #### onDisabledRemoveStorybook
341
-
342
- Type: `boolean`, default: `false`
343
-
344
- If onDisabledRemoveStorybook `true` and `enabled` is `false`, the storybook package will be removed from the build.
345
- This is useful if you want to remove storybook from your production build.
346
-
347
422
  #### useJs
348
423
 
349
424
  Type: `boolean`, default: `false`
@@ -356,6 +431,18 @@ Type: `string`, default: `path.resolve(process.cwd(), './.rnstorybook')`
356
431
 
357
432
  The location of your Storybook configuration directory, which includes `main.ts` and other project-related files.
358
433
 
434
+ #### docTools
435
+
436
+ Type: `boolean`, default: `true`
437
+
438
+ Whether to include doc tools in the storybook.requires file. Doc tools provide additional documentation features and work with `babel-plugin-react-docgen-typescript`.
439
+
440
+ #### liteMode
441
+
442
+ Type: `boolean`, default: `false`
443
+
444
+ Whether to use lite mode for Storybook. In lite mode, the default Storybook UI is mocked out so you don't need to install all its dependencies like react-native-reanimated. This is useful for reducing bundle size and dependencies. Use this when using @storybook/react-native-ui-lite instead of @storybook/react-native-ui.
445
+
359
446
  ### websockets
360
447
 
361
448
  Type: `{ host: string?, port: number? }`, default: `undefined`
@@ -1,4 +1,4 @@
1
- import type { Preview } from '@storybook/react';
1
+ import type { Preview } from '@storybook/react-native';
2
2
 
3
3
  const preview: Preview = {
4
4
  parameters: {
@@ -1,4 +1,4 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
2
 
3
3
  import { View } from 'react-native';
4
4
  import { fn } from 'storybook/test';
@@ -1,4 +1,4 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
2
 
3
3
  import { Header } from './Header';
4
4