mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-21 05:02:39 +08:00
Add CRNA support
1. detect CRNA projects 2. simplify RN and CRNA templates by consolidating app into single `index.js` instead of `index.ios.js` and `index.android.js` 3. notify user of extra setup steps in CLI 4. document CRNA idiosyncrasies in README
This commit is contained in:
parent
f908535e60
commit
3e2673b962
@ -21,7 +21,30 @@ npm -g i @storybook/cli
|
||||
getstorybook
|
||||
```
|
||||
|
||||
## Start the Storybook
|
||||
After you have installed, there are additional steps for `create-react-native-app` apps. See the section for details, otherwise skip to [Start Storybook](#start-storybook)
|
||||
to see the next step.
|
||||
|
||||
## Create React Native App (CRNA)
|
||||
|
||||
If you run `getstorybook` inside a CRNA app, you'll be notified that there is an extra step required to use Storybook.
|
||||
|
||||
The easiest way to use Storybook inside CRNA is to simply replace your App with the Storybook UI, which is possible by replacing `App.js` with a single line of code:
|
||||
|
||||
```js
|
||||
export default from './storybook';
|
||||
```
|
||||
|
||||
This will get you up and running quickly, but then you lose your app!
|
||||
There are multiple options here. for example, you can export conditionally:
|
||||
|
||||
```js
|
||||
import StorybookUI from './storybook';
|
||||
module.exports = __DEV__ ? StorybookUI : App;
|
||||
```
|
||||
|
||||
Alternatively, `StorybookUI` is simply a RN `View` component that can be embedded anywhere in your RN application, e.g. on a tab or within an admin screen.
|
||||
|
||||
## Start Storybook
|
||||
|
||||
After initial setup start the storybook server with the storybook npm script.
|
||||
|
||||
@ -29,14 +52,22 @@ After initial setup start the storybook server with the storybook npm script.
|
||||
npm run storybook
|
||||
```
|
||||
|
||||
also start your mobile app with the `react-native` command.
|
||||
Now, you can open <http://localhost:7007> to view your storybook menus in the browser.
|
||||
|
||||
## Start App
|
||||
|
||||
To see your Storybook stories on the device, you should start your mobile app for the `<platform>` of your choice (typically `ios` or `android`).
|
||||
|
||||
For CRNA apps:
|
||||
```
|
||||
react-native run-ios
|
||||
react-native run-android
|
||||
npm run <platform>
|
||||
```
|
||||
For RN apps:
|
||||
```
|
||||
react-native run-<platform>
|
||||
```
|
||||
|
||||
Now, you can open <http://localhost:7007> to view your storybook.
|
||||
Once your app is started, changing the selected story in web browser will update the story displayed within your mobile app.
|
||||
|
||||
## Learn More
|
||||
|
||||
|
@ -61,6 +61,9 @@ const end = () => {
|
||||
logger.log();
|
||||
};
|
||||
|
||||
const CRNA_DISCUSSION =
|
||||
'https://github.com/storybooks/storybook/blob/master/app/react-native/docs/manual-setup.md';
|
||||
|
||||
switch (projectType) {
|
||||
case types.ALREADY_HAS_STORYBOOK:
|
||||
logger.log();
|
||||
@ -83,6 +86,24 @@ switch (projectType) {
|
||||
.then(end);
|
||||
break;
|
||||
|
||||
case types.REACT_NATIVE_SCRIPTS:
|
||||
require('../generators/REACT_NATIVE_SCRIPTS')
|
||||
.then(commandLog('Adding storybook support to your "Create React Native App" app'))
|
||||
.then(end)
|
||||
.then(() => {
|
||||
logger.log(chalk.red('NOTE: CRNA app installation is not 100% automated.'));
|
||||
logger.log(
|
||||
'To quickly run storybook, replace contents of',
|
||||
chalk.bold('\'./App.js\''),
|
||||
'with:\n'
|
||||
);
|
||||
codeLog(["export default from './storybook';"]);
|
||||
logger.log('\nFor a more complete discussion of options, see:\n');
|
||||
logger.log(chalk.cyan(CRNA_DISCUSSION));
|
||||
logger.log();
|
||||
});
|
||||
break;
|
||||
|
||||
case types.REACT_NATIVE:
|
||||
require('../generators/REACT_NATIVE')
|
||||
.then(commandLog('Adding storybook support to your "React Native" app'))
|
||||
|
@ -13,8 +13,7 @@ module.exports = latestVersion('@storybook/react-native').then(version => {
|
||||
const projectName =
|
||||
dirname && dirname.slice('ios/'.length, dirname.length - '.xcodeproj'.length - 1);
|
||||
if (projectName) {
|
||||
shell.sed('-i', '%APP_NAME%', projectName, 'storybook/index.ios.js');
|
||||
shell.sed('-i', '%APP_NAME%', projectName, 'storybook/index.android.js');
|
||||
shell.sed('-i', '%APP_NAME%', projectName, 'storybook/index.js');
|
||||
}
|
||||
|
||||
const packageJson = helpers.getPackageJson();
|
||||
|
@ -8,3 +8,4 @@ configure(() => {
|
||||
|
||||
const StorybookUI = getStorybookUI({ port: 7007, host: 'localhost' });
|
||||
AppRegistry.registerComponent('%APP_NAME%', () => StorybookUI);
|
||||
export default StorybookUI;
|
26
lib/cli/generators/REACT_NATIVE_SCRIPTS/index.js
Normal file
26
lib/cli/generators/REACT_NATIVE_SCRIPTS/index.js
Normal file
@ -0,0 +1,26 @@
|
||||
const mergeDirs = require('merge-dirs').default;
|
||||
const helpers = require('../../lib/helpers');
|
||||
const path = require('path');
|
||||
const shell = require('shelljs');
|
||||
const latestVersion = require('latest-version');
|
||||
|
||||
module.exports = latestVersion('@storybook/react-native').then(version => {
|
||||
// copy all files from the template directory to project directory
|
||||
mergeDirs(path.resolve(__dirname, 'template/'), '.', 'overwrite');
|
||||
|
||||
const packageJson = helpers.getPackageJson();
|
||||
|
||||
packageJson.dependencies = packageJson.dependencies || {};
|
||||
packageJson.devDependencies = packageJson.devDependencies || {};
|
||||
|
||||
packageJson.devDependencies['@storybook/react-native'] = `^${version}`;
|
||||
|
||||
if (!packageJson.dependencies['react-dom'] && !packageJson.devDependencies['react-dom']) {
|
||||
packageJson.devDependencies['react-dom'] = '^15.5.4';
|
||||
}
|
||||
|
||||
packageJson.scripts = packageJson.scripts || {};
|
||||
packageJson.scripts['storybook'] = 'storybook start -p 7007';
|
||||
|
||||
helpers.writePackageJson(packageJson);
|
||||
});
|
@ -0,0 +1,2 @@
|
||||
import '@storybook/addon-actions/register';
|
||||
import '@storybook/addon-links/register';
|
@ -7,4 +7,4 @@ configure(() => {
|
||||
}, module);
|
||||
|
||||
const StorybookUI = getStorybookUI({ port: 7007, host: 'localhost' });
|
||||
AppRegistry.registerComponent('%APP_NAME%', () => StorybookUI);
|
||||
export default StorybookUI;
|
@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import { TouchableNativeFeedback } from 'react-native';
|
||||
|
||||
export default function Button(props) {
|
||||
return (
|
||||
<TouchableNativeFeedback onPress={props.onPress || Function()}>
|
||||
{props.children}
|
||||
</TouchableNativeFeedback>
|
||||
);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import { TouchableHighlight } from 'react-native';
|
||||
|
||||
export default function Button(props) {
|
||||
return (
|
||||
<TouchableHighlight onPress={props.onPress || Function()}>
|
||||
{props.children}
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import style from './style';
|
||||
|
||||
export default function CenterView(props) {
|
||||
return (
|
||||
<View style={style.main}>
|
||||
{props.children}
|
||||
</View>
|
||||
);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
export default {
|
||||
main: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
};
|
@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
|
||||
export default class Welcome extends React.Component {
|
||||
styles = {
|
||||
wrapper: {
|
||||
flex: 1,
|
||||
padding: 24,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
header: {
|
||||
fontSize: 18,
|
||||
marginBottom: 18,
|
||||
},
|
||||
content: {
|
||||
fontSize: 12,
|
||||
marginBottom: 10,
|
||||
lineHeight: 18,
|
||||
},
|
||||
};
|
||||
|
||||
showApp(e) {
|
||||
e.preventDefault();
|
||||
if (this.props.showApp) this.props.showApp();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={this.styles.wrapper}>
|
||||
<Text style={this.styles.header}>Welcome to React Native Storybook</Text>
|
||||
<Text style={this.styles.content}>
|
||||
This is a UI Component development environment for your React Native app. Here you can display and interact with your UI components as stories. A story is a single state of one or more UI components. You can have as many stories as you want. In other words a story is like a visual test case.
|
||||
</Text>
|
||||
<Text style={this.styles.content}>
|
||||
We have added some stories inside the "storybook/stories" directory for examples. Try editing the "storybook/stories/Welcome.js" file to edit this message.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
import { storiesOf } from '@storybook/react-native';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
|
||||
import Button from './Button';
|
||||
import CenterView from './CenterView';
|
||||
import Welcome from './Welcome';
|
||||
|
||||
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
||||
|
||||
storiesOf('Button', module)
|
||||
.addDecorator(getStory => <CenterView>{getStory()}</CenterView>)
|
||||
.add('with text', () => (
|
||||
<Button onPress={action('clicked-text')}>
|
||||
<Text>Hello Button</Text>
|
||||
</Button>
|
||||
))
|
||||
.add('with some emoji', () => (
|
||||
<Button onPress={action('clicked-emoji')}>
|
||||
<Text>😀 😎 👍 💯</Text>
|
||||
</Button>
|
||||
));
|
@ -34,6 +34,10 @@ module.exports = function detect(options) {
|
||||
return types.REACT_PROJECT;
|
||||
}
|
||||
|
||||
if (packageJson.dependencies && packageJson.devDependencies['react-native-scripts']) {
|
||||
return types.REACT_NATIVE_SCRIPTS;
|
||||
}
|
||||
|
||||
if (packageJson.dependencies && packageJson.dependencies['react-native']) {
|
||||
return types.REACT_NATIVE;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ module.exports = {
|
||||
METEOR: 'METEOR',
|
||||
REACT: 'REACT',
|
||||
REACT_NATIVE: 'REACT_NATIVE',
|
||||
REACT_NATIVE_SCRIPTS: 'REACT_NATIVE_SCRIPTS',
|
||||
REACT_PROJECT: 'REACT_PROJECT',
|
||||
WEBPACK_REACT: 'WEBPACK_REACT',
|
||||
ALREADY_HAS_STORYBOOK: 'ALREADY_HAS_STORYBOOK',
|
||||
|
Loading…
x
Reference in New Issue
Block a user