Skip to content

Commit fe89946

Browse files
FEAT: add storybook (#124)
* feat(storybook): setup and initial configuration of Storybook * feat(dev-menu): add custom Dev Menu item to open Storybook * feat(storybook-icons): add stories for generated icon components * feat(storybook) : update storybook requires genrated file * feat(storybook) : update storybook requires genrated file * feat(storybook-cards): add stories for cards components * feat(env.example): add EXPO_PUBLIC_ENVIRONMENT var to env.exemple * add storybook scripts * add screens guards * clean + storybook app name * storybook commands and README * add form docs stories * storybook: add redirect in app index and update README * clean deps --------- Co-authored-by: Hugo Pérard <hugo.perard@bearstudio.fr>
1 parent 96a319e commit fe89946

File tree

18 files changed

+1371
-129
lines changed

18 files changed

+1371
-129
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ EXPO_PUBLIC_BASE_URL=https://demo.start-ui.com
22

33
# OPTIONAL TO OVERRIDE
44
# EXPO_PUBLIC_AUTH_URL=https://demo.start-ui.com/api/auth
5-
# EXPO_PUBLIC_OPENAPI_URL=https://demo.start-ui.com/api/openapi/app/schema
5+
# EXPO_PUBLIC_OPENAPI_URL=https://demo.start-ui.com/api/openapi/app/schema

.rnstorybook/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import AsyncStorage from '@react-native-async-storage/async-storage';
2+
3+
import { view } from './storybook.requires';
4+
5+
const StorybookUIRoot = view.getStorybookUI({
6+
storage: {
7+
getItem: AsyncStorage.getItem,
8+
setItem: AsyncStorage.setItem,
9+
},
10+
});
11+
12+
export default StorybookUIRoot;

.rnstorybook/main.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { StorybookConfig } from '@storybook/react-native';
2+
3+
const main: StorybookConfig = {
4+
stories: [
5+
'./stories/**/*.stories.?(ts|tsx|js|jsx)',
6+
'../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
7+
],
8+
addons: [
9+
'@storybook/addon-ondevice-controls',
10+
'@storybook/addon-ondevice-actions',
11+
],
12+
};
13+
14+
export default main;

.rnstorybook/storybook.requires.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* do not change this file, it is auto generated by storybook. */
2+
import { start, updateView, View } from '@storybook/react-native';
3+
4+
import '@storybook/addon-ondevice-controls/register';
5+
import '@storybook/addon-ondevice-actions/register';
6+
7+
const normalizedStories = [
8+
{
9+
titlePrefix: '',
10+
directory: './.rnstorybook/stories',
11+
files: '**/*.stories.?(ts|tsx|js|jsx)',
12+
importPathMatcher:
13+
/^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/,
14+
// @ts-ignore
15+
req: require.context(
16+
'./stories',
17+
true,
18+
/^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/
19+
),
20+
},
21+
{
22+
titlePrefix: '',
23+
directory: './src',
24+
files: '**/*.stories.@(js|jsx|mjs|ts|tsx)',
25+
importPathMatcher:
26+
/^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|mjs|ts|tsx))$/,
27+
// @ts-ignore
28+
req: require.context(
29+
'../src',
30+
true,
31+
/^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|mjs|ts|tsx))$/
32+
),
33+
},
34+
];
35+
36+
declare global {
37+
var view: View;
38+
var STORIES: typeof normalizedStories;
39+
}
40+
41+
const annotations = [require('@storybook/react-native/preview')];
42+
43+
global.STORIES = normalizedStories;
44+
45+
// @ts-ignore
46+
module?.hot?.accept?.();
47+
48+
if (!global.view) {
49+
global.view = start({
50+
annotations,
51+
storyEntries: normalizedStories,
52+
});
53+
} else {
54+
updateView(global.view, annotations, normalizedStories);
55+
}
56+
57+
export const view: View = global.view;

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ pnpm install # Install dependencies
3333

3434
## Environment variables
3535

36-
🚨 Using Expo Go, local development urls should not be `localhost`, use public IP instead
36+
37+
> [!TIP]
38+
> Using Expo Go, local development urls should not be `localhost`, use public IP instead
3739
3840
```bash
3941
EXPO_PUBLIC_BASE_URL # Base URL of your server, usefull if you are using Start UI [web]
@@ -76,6 +78,18 @@ pnpm dev:ios # To run with local ios build
7678
pnpm dev:android # To run with local android build
7779
```
7880

81+
## Storybook
82+
83+
Storybook is managed as a specific mode of the app that is launch apart in port 8083
84+
85+
```bash
86+
pnpm storybook # To run app in storybook mode
87+
```
88+
89+
> [!TIP]
90+
> You can open Storybook in another tab and switch between the app and Storybook by pressing `i` or `a` in each terminal.
91+
92+
7993
## Generate custom icons components from svg files
8094

8195
Put the custom svg files into the `app/components/icons/svg-sources` folder and then run the following command:

app.config.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import { ExpoConfig } from 'expo/config';
33
const BUILD_NUMBER: `${number}` = '1';
44
const EXPO_PROJECT_ID = 'af6ae74c-f04d-497a-9733-b2b7539f77c5';
55

6+
const appPrefix =
7+
process.env.EXPO_PUBLIC_ENVIRONMENT === 'storybook' ? 'Storybook • ' : '';
8+
69
export default {
7-
name: 'Start UI [native]',
10+
name: appPrefix + 'Start UI [native]',
811
slug: 'start-ui-native-v9iizxkbojzedvpfkfzcq',
912
scheme: 'start-ui-native',
1013
owner: 'bearstudio',
@@ -24,7 +27,7 @@ export default {
2427
bundleIdentifier: 'com.bearstudio.startuinative',
2528
buildNumber: BUILD_NUMBER,
2629
supportsTablet: true,
27-
// appStoreUrl: 'https://apps.apple.com/fr/app/bearstudio/xxxx',
30+
// appStoreUrl: 'https://apps.apple.com/fr/app/bearstudio/startuinative',
2831
},
2932
android: {
3033
package: 'com.bearstudio.startuinative',
@@ -63,6 +66,7 @@ export default {
6366
url: `https://u.expo.dev/${EXPO_PROJECT_ID}`,
6467
},
6568
extra: {
69+
isStorybook: process.env.EXPO_PUBLIC_ENVIRONMENT === 'storybook',
6670
eas: {
6771
projectId: EXPO_PROJECT_ID,
6872
},

metro.config.cjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* eslint-disable no-undef */
2+
/* eslint-disable @typescript-eslint/no-require-imports */
3+
const path = require('path');
4+
const { getDefaultConfig } = require('expo/metro-config');
5+
6+
const withStorybook = require('@storybook/react-native/metro/withStorybook');
7+
8+
/** @type {import('expo/metro-config').MetroConfig} */
9+
const config = getDefaultConfig(__dirname);
10+
11+
module.exports = withStorybook(config, {
12+
enabled: true,
13+
configPath: path.resolve(__dirname, './.rnstorybook'),
14+
});

package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"dev": "expo start --go",
1212
"dev:android": "expo run:android",
1313
"dev:ios": "expo run:ios",
14+
"storybook": "EXPO_PUBLIC_ENVIRONMENT='storybook' expo start --go --port 8083",
1415
"lint": "run-p lint:*",
1516
"lint:eslint": "eslint ./src --fix",
1617
"lint:ts": "tsc --noEmit",
@@ -35,6 +36,7 @@
3536
"dayjs": "1.11.18",
3637
"expo": "54.0.13",
3738
"expo-application": "7.0.7",
39+
"expo-constants": "18.0.9",
3840
"expo-device": "8.0.9",
3941
"expo-font": "14.0.9",
4042
"expo-haptics": "15.0.7",
@@ -69,9 +71,13 @@
6971
"zod": "4.1.11"
7072
},
7173
"devDependencies": {
74+
"@babel/core": "7.28.4",
7275
"@eslint-react/eslint-plugin": "1.53.1",
7376
"@eslint/js": "9.36.0",
7477
"@hey-api/openapi-ts": "0.85.1",
78+
"@storybook/addon-ondevice-actions": "9.1.4",
79+
"@storybook/addon-ondevice-controls": "9.1.4",
80+
"@storybook/react-native": "9.1.4",
7581
"@svgr/cli": "8.1.0",
7682
"@types/node": "24.6.1",
7783
"@types/react": "19.1.13",
@@ -87,6 +93,7 @@
8793
"lefthook": "1.13.4",
8894
"npm-run-all": "4.1.5",
8995
"prettier": "3.6.2",
96+
"storybook": "9.1.10",
9097
"ts-plugin-sort-import-suggestions": "1.0.4",
9198
"typescript": "5.9.2",
9299
"typescript-eslint": "8.44.1"
@@ -121,6 +128,9 @@
121128
"onlyBuiltDependencies": [
122129
"lefthook",
123130
"unrs-resolver"
124-
]
131+
],
132+
"overrides": {
133+
"@react-native-community/slider": "5.0.1"
134+
}
125135
}
126136
}

0 commit comments

Comments
 (0)