Skip to content

Commit 347b300

Browse files
authored
feat: new withStorybookConfig metro wrapper to replace withStorybook in the future (#776)
* feat: simpler withStorybook configuration * fix * v9.1.1-alpha.0 * docs for sharing * docs * Update sharing-storybook.md * docs * Update section headers in sharing-storybook.md for clarity * docs * fix: tty/os errors
1 parent 4564881 commit 347b300

File tree

18 files changed

+553
-63
lines changed

18 files changed

+553
-63
lines changed
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
---
2+
sidebar_position: 5
3+
---
4+
5+
# Sharing Storybook
6+
7+
Storybook is a great tool for sharing your components with your team. It's a great way to get feedback on your components and to make sure they're working as expected.
8+
9+
## Share on iOS via TestFlight
10+
11+
On iOS internal builds are often shared via ad hoc provisioning. The problem with this is that you need to create a new build anytime you want to give a new team member access to the app. Not only that but they will need to have their own device in developer mode in order to install it. Using TestFlight enables you to share your app with up to 10k without the need to rebuild each time you want to give someone access.
12+
13+
The one complication is that usually your TestFlight build is a production build of your app, this means you can't usually use this for a developer preview. However what you can do is create a separate app in App Center that is specifically used for preview builds and won't ever ship to the App Store.
14+
15+
The following guide will be written for expo because its simpler to get setup, but the same principles apply to other frameworks. The important part will be having a preview version of your app that you ship only internally.
16+
17+
### Get setup
18+
19+
If you don't already have an app, lets create one to get started with.
20+
21+
```bash
22+
npx create-expo-app --template expo-template-storybook@next AwesomeStorybook
23+
```
24+
25+
This will create a new expo app with storybook already setup.
26+
27+
```bash
28+
cd AwesomeStorybook
29+
```
30+
31+
### Configure eas
32+
33+
Next we'll want to configure eas and setup eas updates.
34+
35+
if you don't already have it then install the eas cli
36+
37+
```bash
38+
npm install -g eas-cli
39+
```
40+
41+
Then lets have it setup the project for us.
42+
43+
If you run each of these commands you'll end up with a project setup for eas builds and updates.
44+
45+
```bash
46+
eas login
47+
eas init
48+
eas build:configure -p all
49+
eas update:configure
50+
```
51+
52+
You should now have an eas.json file in your project.
53+
54+
We're going to want to make a few tweaks to setup the preview builds I mentioned earlier.
55+
56+
Lets add a storybook build type and use the store distribution with auto increment. We'll set this up as a preview environment with a different bundle identifier and app name than your production app.
57+
58+
```json
59+
{
60+
"build": {
61+
// other build types...
62+
63+
// add storybook build type here
64+
"storybook": {
65+
"distribution": "store",
66+
"channel": "storybook",
67+
"autoIncrement": true,
68+
"ios": {
69+
"simulator": false
70+
},
71+
"env": {
72+
"EXPO_PUBLIC_ENVIRONMENT": "storybook",
73+
"EXPO_PUBLIC_STORYBOOK_ENABLED": "true"
74+
}
75+
}
76+
},
77+
"submit": {
78+
// other submit types...
79+
80+
// add storybook submit type here
81+
"storybook": {
82+
"ios": {
83+
"bundleIdentifier": "com.example.myapp-storybook",
84+
"appName": "My App Storybook"
85+
}
86+
}
87+
}
88+
}
89+
```
90+
91+
Make sure to replace `com.example.myapp-storybook` and `My App` with your own bundle identifier and app name.
92+
93+
Now lets add an `app.config.ts` file to use the environment variable to change the bundle identifier.
94+
Note that when you have an app.json and app.config.ts file you can extend the app.json config since its passed to the config function.
95+
96+
```ts
97+
// CREATE THIS FILE
98+
// app.config.ts
99+
import { type ExpoConfig, ConfigContext } from 'expo/config';
100+
101+
function getBundleIdentifier() {
102+
const isStorybook = process.env.EXPO_PUBLIC_ENVIRONMENT === 'storybook';
103+
104+
if (isStorybook) {
105+
return 'com.example.myapp.storybook';
106+
}
107+
108+
return 'com.example.myapp';
109+
}
110+
111+
function config({ config }: ConfigContext): Partial<ExpoConfig> {
112+
return {
113+
// this is the config from app.json
114+
...config,
115+
ios: {
116+
...config.ios,
117+
bundleIdentifier: getBundleIdentifier(),
118+
infoPlist: {
119+
...config.ios?.infoPlist,
120+
ITSAppUsesNonExemptEncryption: false,
121+
},
122+
},
123+
};
124+
}
125+
126+
export default config;
127+
```
128+
129+
```bash
130+
eas build -p ios --submit --profile storybook
131+
```
132+
133+
You will be asked to confirm a few things but you can usually just press enter to accept the defaults.
134+
135+
If all goes well you should get an email saying your app is ready to be installed through TestFlight.
136+
137+
<img height="400" alt="tfinvitesb" src="https://github.com/user-attachments/assets/aacd14aa-bf60-4f23-b78a-9418cc77407c" />
138+
139+
From here just install the app and you should see storybook.
140+
141+
https://github.com/user-attachments/assets/7d8d3970-8c46-4a74-822d-0abe35cfb98b
142+
143+
## Android
144+
145+
For android you can make either an internal testing build available on the play store or you can create an internal distribution with an apk buildType
146+
147+
```json
148+
{
149+
"build": {
150+
// other build types...
151+
152+
"storybook": {
153+
"distribution": "store",
154+
"channel": "storybook",
155+
"autoIncrement": true,
156+
"ios": {
157+
"simulator": false
158+
},
159+
"env": {
160+
"EXPO_PUBLIC_ENVIRONMENT": "storybook",
161+
"EXPO_PUBLIC_STORYBOOK_ENABLED": "true"
162+
}
163+
},
164+
// 👇 for internal sharing of apk builds
165+
"storybook-internal": {
166+
"extends": "storybook",
167+
"distribution": "internal",
168+
"android": { "buildType": "apk" }
169+
}
170+
}
171+
}
172+
```
173+
174+
Then update your `app.config.ts`
175+
176+
```tsx
177+
function config({ config }: ConfigContext): Partial<ExpoConfig> {
178+
return {
179+
// this is the config from app.json
180+
...config,
181+
// rest of the config...
182+
android: {
183+
...config.android,
184+
package: getBundleIdentifier(),
185+
},
186+
};
187+
}
188+
```
189+
190+
Now to create an internal build run
191+
192+
```bash
193+
eas build -p android --profile storybook-internal
194+
```
195+
196+
When you open up the build in eas you’ll see a button to install that will give you a QR code and a link that you can use to download the apk directly.
197+
<img width="1170" height="344" alt="sbandr" src="https://github.com/user-attachments/assets/cdc3a11b-2422-4378-be2b-1f9233283c4b" />
198+
199+
## Publishing on the Web
200+
201+
The React Native Storybook UI is compatible with React Native Web so if you are supporting the web with your components then you’ll be able to use `expo export` and `eas deploy` to deploy your stories on the web.
202+
203+
First build your app for web:
204+
205+
```tsx
206+
EXPO_PUBLIC_ENVIRONMENT=storybook bun expo export --platform web
207+
```
208+
209+
Then deploy:
210+
211+
```tsx
212+
eas deploy
213+
```
214+
215+
Heres one I deployed earlier: https://sharestorybook--qclgxuc645.expo.app/

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "docs",
3-
"version": "9.1.0",
3+
"version": "9.1.1-alpha.0",
44
"private": true,
55
"scripts": {
66
"docusaurus": "docusaurus",

examples/expo-example/metro.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ defaultConfig.resolver.nodeModulesPaths = [
2020
path.resolve(workspaceRoot, 'node_modules'),
2121
];
2222

23-
const withStorybook = require('@storybook/react-native/metro/withStorybook');
23+
const { withStorybookConfig } = require('@storybook/react-native/metro/withStorybookConfig');
2424

25-
module.exports = withStorybook(defaultConfig);
25+
module.exports = withStorybookConfig(defaultConfig);
2626

2727
/* , {
2828
enabled: process.env.STORYBOOK_ENABLED === 'true',

examples/expo-example/package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "expo-example",
3-
"version": "9.1.0",
3+
"version": "9.1.1-alpha.0",
44
"private": true,
55
"main": "index.js",
66
"scripts": {
@@ -28,16 +28,16 @@
2828
"@react-native-async-storage/async-storage": "2.1.2",
2929
"@react-native-community/datetimepicker": "8.3.0",
3030
"@react-native-community/slider": "4.5.6",
31-
"@storybook/addon-ondevice-actions": "^9.1.0",
32-
"@storybook/addon-ondevice-backgrounds": "^9.1.0",
33-
"@storybook/addon-ondevice-controls": "^9.1.0",
34-
"@storybook/addon-ondevice-notes": "^9.1.0",
31+
"@storybook/addon-ondevice-actions": "^9.1.1-alpha.0",
32+
"@storybook/addon-ondevice-backgrounds": "^9.1.1-alpha.0",
33+
"@storybook/addon-ondevice-controls": "^9.1.1-alpha.0",
34+
"@storybook/addon-ondevice-notes": "^9.1.1-alpha.0",
3535
"@storybook/addon-react-native-server": "^1.0.0",
3636
"@storybook/global": "^5.0.0",
3737
"@storybook/react": "^9.1.0",
38-
"@storybook/react-native": "^9.1.0",
39-
"@storybook/react-native-theming": "^9.1.0",
40-
"@storybook/react-native-ui-lite": "^9.1.0",
38+
"@storybook/react-native": "^9.1.1-alpha.0",
39+
"@storybook/react-native-theming": "^9.1.1-alpha.0",
40+
"@storybook/react-native-ui-lite": "^9.1.1-alpha.0",
4141
"@storybook/react-native-web-vite": "^9.1.0",
4242
"babel-plugin-react-compiler": "^19.1.0-rc.2",
4343
"expo": "~53.0.9",

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"npmClient": "yarn",
33
"registry": "https://registry.npmjs.org",
4-
"version": "9.1.0"
4+
"version": "9.1.1-alpha.0"
55
}

packages/ondevice-actions/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@storybook/addon-ondevice-actions",
3-
"version": "9.1.0",
3+
"version": "9.1.1-alpha.0",
44
"description": "Action Logger addon for react-native storybook",
55
"keywords": [
66
"storybook"

packages/ondevice-backgrounds/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@storybook/addon-ondevice-backgrounds",
3-
"version": "9.1.0",
3+
"version": "9.1.1-alpha.0",
44
"description": "A react-native storybook addon to show different backgrounds for your preview",
55
"keywords": [
66
"addon",
@@ -32,7 +32,7 @@
3232
"dev": "tsc --watch"
3333
},
3434
"dependencies": {
35-
"@storybook/react-native-theming": "^9.1.0"
35+
"@storybook/react-native-theming": "^9.1.1-alpha.0"
3636
},
3737
"devDependencies": {
3838
"typescript": "~5.8.3"

packages/ondevice-controls/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@storybook/addon-ondevice-controls",
3-
"version": "9.1.0",
3+
"version": "9.1.1-alpha.0",
44
"description": "Display storybook controls on your device.",
55
"keywords": [
66
"addon",
@@ -30,8 +30,8 @@
3030
"copyimages": "cross-env-shell cp -r src/components/color-picker/resources dist/components/color-picker/resources"
3131
},
3232
"dependencies": {
33-
"@storybook/react-native-theming": "^9.1.0",
34-
"@storybook/react-native-ui-common": "^9.1.0",
33+
"@storybook/react-native-theming": "^9.1.1-alpha.0",
34+
"@storybook/react-native-ui-common": "^9.1.1-alpha.0",
3535
"deep-equal": "^1.0.1",
3636
"prop-types": "^15.7.2",
3737
"react-native-modal-datetime-picker": "^18.0.0",

packages/ondevice-notes/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@storybook/addon-ondevice-notes",
3-
"version": "9.1.0",
3+
"version": "9.1.1-alpha.0",
44
"description": "Write notes for your react-native Storybook stories.",
55
"keywords": [
66
"addon",
@@ -29,7 +29,7 @@
2929
"dev": "tsc --watch"
3030
},
3131
"dependencies": {
32-
"@storybook/react-native-theming": "^9.1.0",
32+
"@storybook/react-native-theming": "^9.1.1-alpha.0",
3333
"react-native-markdown-display": "^7.0.2"
3434
},
3535
"devDependencies": {

packages/react-native-theming/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@storybook/react-native-theming",
3-
"version": "9.1.0",
3+
"version": "9.1.1-alpha.0",
44
"description": "A wrapper library around emotion 11 to provide theming support for react-native storybook",
55
"keywords": [
66
"react",

0 commit comments

Comments
 (0)