Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added create-react-native-app support #1117

Merged
merged 6 commits into from
May 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions app/react-native/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,53 @@ 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good coverage of options, nice work


## Start Storybook

After initial setup start the storybook server with the storybook npm script.

```shell
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:
```
npm run <platform>
```
For RN apps:
```
react-native run-ios
react-native run-android
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

Expand Down
19 changes: 19 additions & 0 deletions lib/cli/bin/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -83,6 +86,22 @@ switch (projectType) {
.then(end);
break;

case types.REACT_NATIVE_SCRIPTS: {
const app = chalk.bold('"./App.js"');
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 ${app} with:\n`);
codeLog(["export default from './storybook';"]); // eslint-disable-line
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'))
Expand Down
3 changes: 1 addition & 2 deletions lib/cli/generators/REACT_NATIVE/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ configure(() => {

const StorybookUI = getStorybookUI({ port: 7007, host: 'localhost' });
AppRegistry.registerComponent('%APP_NAME%', () => StorybookUI);
export default StorybookUI;
25 changes: 25 additions & 0 deletions lib/cli/generators/REACT_NATIVE_SCRIPTS/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const mergeDirs = require('merge-dirs').default;
const helpers = require('../../lib/helpers');
const path = require('path');
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';
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one 👍


packageJson.scripts = packageJson.scripts || {};
packageJson.scripts['storybook'] = 'storybook start -p 7007';

helpers.writePackageJson(packageJson);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ configure(() => {
}, module);

const StorybookUI = getStorybookUI({ port: 7007, host: 'localhost' });
AppRegistry.registerComponent('%APP_NAME%', () => StorybookUI);
export default StorybookUI;
Original file line number Diff line number Diff line change
@@ -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>
);
}
Original file line number Diff line number Diff line change
@@ -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>
);
}
Original file line number Diff line number Diff line change
@@ -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>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
main: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
};
Original file line number Diff line number Diff line change
@@ -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>
);
}
}
Original file line number Diff line number Diff line change
@@ -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>
));
4 changes: 4 additions & 0 deletions lib/cli/lib/detect.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions lib/cli/lib/project_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down