[MM-28845]: Add storybook to mobile repo (#4870)
*Summary* - This PR adds storybook into the mobile repo, and adds a sample story for the existing "loading" component. - In the root of the repo run `npm run storybook`. This step automatically scans and loads all stories. A new browser tab will open with the storybook interface. You can configure the storybook host url by updating the .env file in the root of the repo. This might be required if you're using a real device. When running in an emulator, the code tries to use the default network values. - Then run the usual `npm run android` (or `npm run ios`) and `npm run start` commands - Storybook has been integrated into the react-native-dev-menu. When the app is running in the emulator press CTRL+M or CMD+M to open the dev menu and select "Storybook". If running on a real device, shaking the device will bring up the react-native dev menu. You can also press d in the terminal where you ran npm run start to get the app running. - The storybook interface will open in the mobile app. The stories can be controlled either through the desktop browser storybook UI or the mobile browser storybook UI. Both will render the component on the device. *Ticket Link* https://mattermost.atlassian.net/browse/MM-28845 *Device Information* This PR was tested on: Iphone 11 emulator running ios 13.7 Pixel 3XL emulator running Android 10
This commit is contained in:
parent
4e53683a3a
commit
1914b770e5
14 changed files with 7858 additions and 38 deletions
2
.env
Normal file
2
.env
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
STORYBOOK_PORT=
|
||||
STORYBOOK_HOST=
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -5,6 +5,8 @@ build-ios
|
|||
server.PID
|
||||
mattermost.keystore
|
||||
tmp/
|
||||
.env
|
||||
env.d.ts
|
||||
|
||||
# OSX
|
||||
#
|
||||
|
|
|
|||
6
.storybook/main.js
Normal file
6
.storybook/main.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
"stories": [
|
||||
"../app/components/**/*.stories.mdx",
|
||||
"../app/components/**/*.stories.@(js|jsx|ts|tsx)"
|
||||
],
|
||||
}
|
||||
5
.storybook/preview.js
Normal file
5
.storybook/preview.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
}
|
||||
|
||||
17
app/components/loading.stories.tsx
Normal file
17
app/components/loading.stories.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
|
||||
import {storiesOf} from '@storybook/react-native';
|
||||
import {withKnobs, select} from '@storybook/addon-knobs';
|
||||
|
||||
import Loading from './loading';
|
||||
|
||||
storiesOf('Loading Icon Story', module).
|
||||
addDecorator(withKnobs).
|
||||
add('loading icon', () => (
|
||||
<Loading
|
||||
size={select('size', {Large: 'large', Small: 'small'}, 'large')}
|
||||
color={select('color', {Red: 'red', Blue: 'blue', Yellow: 'yellow', Black: 'black'}, 'red')}
|
||||
/>
|
||||
));
|
||||
|
|
@ -28,6 +28,14 @@ module.exports = {
|
|||
'@websocket': './app/client/websocket',
|
||||
},
|
||||
}],
|
||||
['module:react-native-dotenv', {
|
||||
moduleName: '@env',
|
||||
path: '.env',
|
||||
blacklist: null,
|
||||
whitelist: null,
|
||||
safe: false,
|
||||
allowUndefined: true,
|
||||
}],
|
||||
],
|
||||
exclude: ['**/*.png', '**/*.jpg', '**/*.gif'],
|
||||
};
|
||||
|
|
|
|||
8
env.d.ts
vendored
Normal file
8
env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// So that typescript doesn't complain about importing `@env` through react-native-dotenv
|
||||
declare module '@env' {
|
||||
export const STORYBOOK_HOST: string;
|
||||
export const STORYBOOK_PORT: number;
|
||||
}
|
||||
1
index.js
1
index.js
|
|
@ -26,6 +26,7 @@ if (__DEV__) {
|
|||
'Require cycle: node_modules/react-native/Libraries/Network/fetch.js',
|
||||
'Warning: Cannot update a component from inside the function body of a different component',
|
||||
]);
|
||||
require('storybook/mattermost_storybook.ts');
|
||||
}
|
||||
|
||||
const setFontFamily = () => {
|
||||
|
|
|
|||
7770
package-lock.json
generated
7770
package-lock.json
generated
File diff suppressed because it is too large
Load diff
22
package.json
22
package.json
|
|
@ -97,6 +97,10 @@
|
|||
"@babel/preset-env": "7.12.1",
|
||||
"@babel/register": "7.12.1",
|
||||
"@react-native-community/eslint-config": "2.0.0",
|
||||
"@storybook/addon-knobs": "6.0.26",
|
||||
"@storybook/addon-ondevice-knobs": "5.3.23",
|
||||
"@storybook/react-native": "5.3.23",
|
||||
"@storybook/react-native-server": "5.3.23",
|
||||
"@testing-library/react-native": "7.1.0",
|
||||
"@types/enzyme": "3.10.7",
|
||||
"@types/enzyme-adapter-react-16": "1.0.6",
|
||||
|
|
@ -111,6 +115,7 @@
|
|||
"@typescript-eslint/parser": "3.10.1",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "26.6.1",
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-plugin-module-resolver": "4.0.0",
|
||||
"babel-plugin-transform-remove-console": "6.9.4",
|
||||
"deep-freeze": "0.0.1",
|
||||
|
|
@ -139,6 +144,9 @@
|
|||
"nyc": "15.1.0",
|
||||
"patch-package": "6.2.2",
|
||||
"react-dom": "16.13.1",
|
||||
"react-native-dev-menu": "4.0.2",
|
||||
"react-native-dotenv": "2.4.2",
|
||||
"react-native-storybook-loader": "2.0.2",
|
||||
"redux-mock-store": "1.5.4",
|
||||
"redux-persist-node-storage": "2.0.0",
|
||||
"socketcluster": "16.0.1",
|
||||
|
|
@ -177,6 +185,18 @@
|
|||
"build:ios-unsigned": "./scripts/build.sh ipa unsigned",
|
||||
"build:ios-sim": "./scripts/build.sh ipa simulator",
|
||||
"build:android": "./scripts/build.sh apk",
|
||||
"build:android-unsigned": "./scripts/build.sh apk unsigned"
|
||||
"build:android-unsigned": "./scripts/build.sh apk unsigned",
|
||||
"build-storybook": "build-storybook",
|
||||
"prestorybook": "rnstl",
|
||||
"storybook": "start-storybook -p 7007"
|
||||
},
|
||||
"config": {
|
||||
"react-native-storybook-loader": {
|
||||
"searchDir": [
|
||||
"./app/components"
|
||||
],
|
||||
"pattern": "**/*.stories.@(js|jsx|ts|tsx)",
|
||||
"outputFile": "./storybook/storyLoader.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
storybook/addons.ts
Normal file
3
storybook/addons.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import '@storybook/addon-knobs/register';
|
||||
31
storybook/index.ts
Normal file
31
storybook/index.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Platform} from 'react-native';
|
||||
import {STORYBOOK_HOST, STORYBOOK_PORT} from '@env';
|
||||
import {getStorybookUI, configure} from '@storybook/react-native';
|
||||
|
||||
// load react-native addons for storybook rn
|
||||
import '@storybook/addon-ondevice-knobs/register';
|
||||
|
||||
import {loadStories} from './storyLoader';
|
||||
|
||||
// import stories
|
||||
configure(() => {
|
||||
loadStories();
|
||||
}, module);
|
||||
|
||||
// this seems to be required to get react-native-dotenv to load the env variables
|
||||
// properly. Possibly something related to babel-loader
|
||||
const port = STORYBOOK_PORT;
|
||||
const host = STORYBOOK_HOST;
|
||||
|
||||
// Refer to https://github.com/storybookjs/storybook/tree/master/app/react-native#start-command-parameters
|
||||
// To find allowed options for getStorybookUI
|
||||
const StorybookUIRoot = getStorybookUI({
|
||||
port: port || 7007,
|
||||
host: host || (Platform.OS === 'ios' ? 'localhost' : '10.0.2.2'),
|
||||
onDeviceUI: true,
|
||||
resetStorybook: true,
|
||||
});
|
||||
|
||||
export default StorybookUIRoot;
|
||||
8
storybook/mattermost_storybook.ts
Normal file
8
storybook/mattermost_storybook.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
import {goToScreen} from '@actions/navigation';
|
||||
|
||||
import DevMenu from 'react-native-dev-menu';
|
||||
DevMenu.addItem('StoryBook', () => goToScreen('StoryBook', 'StoryBook'));
|
||||
Navigation.registerComponent('StoryBook', () => require('../storybook').default, () => require('../storybook').default);
|
||||
13
storybook/storyLoader.js
Normal file
13
storybook/storyLoader.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
function loadStories() {
|
||||
require('../app/components/loading.stories');
|
||||
}
|
||||
|
||||
const stories = ['../app/components/loading.stories'];
|
||||
|
||||
module.exports = {
|
||||
loadStories,
|
||||
stories,
|
||||
};
|
||||
Loading…
Reference in a new issue