diff --git a/README.md b/README.md index 31b74cf74b83..9155674c39ee 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Now you can develop and design React UI components without running your app. -![React Storybook Screenshot](docs/react-storybook-screenshot.png) +![React Storybook Screenshot](docs/react_storybook_screenshot.png) You just load your UI components into the React Storybook and start developing them. @@ -41,7 +41,7 @@ npm run storybook This will start your Storybook in . Open that URL in your browser. You will see the React Storybook UI: -![React Storybook in action](docs/react-storybook-demo.gif) +![React Storybook in action](docs/react_storybook_demo.gif) Edit some of the components in the `components` directory and see how they reflect in the Storybook UI. We define stories inside the `components/stories` directory. Have a play with that as well. @@ -120,13 +120,11 @@ That's it. Now simply run `npm run storybook` and start developing your componen There are many things you can do with React Storybook. You can explore them with the following links: -* [Setting up for CSS](docs/setting-up-for-css.md) -* [API and configurations](docs/api.md) -* [Guideline for writing stories](docs/guidelines.md) +* [Writing Stories](docs/writing_stories.md) +* [Setting up for CSS](docs/setting_up_for_css.md) +* [Configuration APIs](docs/configure_storybook.md) * [Known Issues](docs/known_issues.md) -* [How to Contribute](CONTRIBUTING.md) -* [Storybooks.io](https://storybooks.io/?utm_source=github&utm_medium=link&utm_campaign=react-storybook) -* How React Storybook works (coming soon) +* [Storybooks.io](https://storybooks.io/?utm_source=github&utm_medium=link&utm_campaign=react-storybook) #### New: React Storybook meets GitHub @@ -139,5 +137,3 @@ React Storybook is very powerful and you can use it with any kind of app. Here's * [Very simple demo](https://github.com/kadira-samples/react-storybook-simple-demo) * [Redux to-do app](https://github.com/kadira-samples/react-storybook-demo) * [Meteor app (Mantra)](https://github.com/mantrajs/mantra-sample-blog-app) -* Simple Meteor app (coming soon) -* Material UI component browser (coming soon) diff --git a/docs/.DS_Store b/docs/.DS_Store new file mode 100644 index 000000000000..5008ddfcf53c Binary files /dev/null and b/docs/.DS_Store differ diff --git a/docs/api.md b/docs/configure_storybook.md similarity index 57% rename from docs/api.md rename to docs/configure_storybook.md index 0c2eec72b61e..9a5ff55f478b 100644 --- a/docs/api.md +++ b/docs/configure_storybook.md @@ -1,167 +1,24 @@ -# API +# Configure Storybook You can configure React Storybook in different ways. We'll discuss them here. ## TOC +* [Basic Configurations](#basic-configurations) + * [Loading Modules](#loading-modules) + * [Load Common CSS Files](#load-common-css-files) + * [Configure Modules for Testing](#configure-modules-for-testing) * [Command Line API](#command-line-api) * [Port](#port) * [Static Directory](#static-directory) * [Configuration Directory](#configuration-directory) * [Static Builder](#static-builder) -* [Story Creation API](#story-creation-api) - * [Creating Stories](#creating-stories) - * [Creating Actions](#creating-actions) - * [Linking Stories](#linking-stories) -* [Basic Configurations](#basic-configurations) - * [Loading Modules](#loading-modules) - * [Load Common CSS Files](#load-common-css-files) - * [Configure Modules for Testing](#configure-modules-for-testing) * [Custom Webpack Configurations](#custom-webpack-configurations) -* [Load Custom HTML Head](#load-custom-html-head) - -## Command Line API - -React Storybook comes with a command line API, which you usually use inside a NPM script. Here's the options it has: - -### Port - -You must set a port on which React Storybook starts its web server. Here's how to specify it: - -```sh -start-storybook -p 6977 -``` - -### Static Directory - -Sometimes, you ship your static files directly inside your project. In Meteor apps, this is done with the `public` directory in the app root. So, you can ask React Storybook to serve those static files. + * [Add Custom CSS Loaders](#add-custom-css-loaders) + * [Customizing The UI](#customizing-the-ui) + * [Other Configurations](#other-configurations) +* [Load Custom HTML Head Content](#load-custom-html-head-content) -Here's how to tell React Storybook to use that directory to load static files: - -```sh -start-storybook -p 6977 -s ./public -``` - -### Configuration Directory - -React Storybook uses `.storybook` directory as a default location for its [basic](#basic-configurations) and [custom webpack](#custom-webpack-configurations) configuration. - -Here's how to tell React Storybook to use a custom directory to load your configuration files: - -```sh -start-storybook -p 6977 -s ./public -c ./storybook-config -``` - -### Static Builder - -With Static Builder, you could convert your whole Storybook into a static site. Then, you can deploy that into any static site hosting service including "GitHub Pages". - -Add following script as an NPM script: - -```sh -build-storybook -o storybook-build-dir -``` - -Then it'll build and save a set of static files into the `storybook-build-dir` directory. You can access them by running a following python static server: - -```python -python -m SimpleHTTPServer -``` - -For more information, run `build-storybook -h`. - -## Story Creation API - -We need to create stories to show your components inside React Storybook. For that, we need to use this API. - -### Creating Stories - -This is how you can create stories: - -```js -import React from 'react'; -import { storiesOf } from '@kadira/storybook'; - -storiesOf('Button', module) - .add('with a text', () => ( - - )) - .add('with no text', () => ( - - )); -``` - -Here you can chain the `add` method and create as many stories as you need. - -### Creating Actions - -Usually, our components accept event handlers. Actions help us to debug those event handlers. These actions are logged in the `Action Logger` info window in React Storybook. - -This is how we can create an action: - -```js -import React from 'react'; -import { storiesOf, action } from '@kadira/storybook'; - -storiesOf('Button', module) - .add('with a text', () => ( - - )); -``` - -Here we create an action named `click the button`. It gives a function to the `onClick` prop in our button. - -Then, when you click on the button, it will log something like this into the Action Logger: - -```js -{ - "name": "click the button", - "args": [ - "[SyntheticMouseEvent]", - ".1", - { - "isTrusted": false - } - ] -} -``` - -Here we can see the name we've mentioned when creating the action. After that, we can see the arguments passed to the `onClick` event handler. In this case, we've three arguments. `[SyntheticMouseEvent]` is the actual event object passed by React and you can use that to get more details. - -> For simplicity, React Storybook does not show the actual object. Instead it will show `[SyntheticMouseEvent]`. - -### Linking Stories - -Sometimes, we may need to link stories. With that, we could use Storybook as a prototype builder. (like [InVision](https://www.invisionapp.com/), [Framer.js](http://framerjs.com/)). Here's how to do that. - -Let's say, we've a Toggle button and we need to change the story as we click the button. This is how we do it: - -```js -import { linkTo } from @kadira/storybook - -storiesOf('Toggle', module) - .add('on', () => { - return - }) - .add('off', () => { - return - }); -``` - -Have a look at the `linkTo` function: - -```js -linkTo('Toggle', 'off') -``` - -With that, you can link an event prop to any story in the Storybook. - -* First parameter is the the story kind name (what you named with `storiesOf`). -* Second parameter is the story name (what you named with `.add`). - -> You can also pass a function instead for any of above parameter. That function accepts arguments emitted by the event and it should return a string. - -Have a look at [PR86](https://github.com/kadirahq/react-storybook/pull/86) for more information. ## Basic Configurations @@ -234,11 +91,59 @@ function loadStories() { configure(loadStories, module); ``` -## Custom Webpack Configurations +## Command Line API + +React Storybook comes with a command line API, which you usually use inside a NPM script. Here's the options it has: + +### Port + +You must set a port on which React Storybook starts its web server. Here's how to specify it: + +```sh +start-storybook -p 6977 +``` + +### Static Directory + +Sometimes, you ship your static files directly inside your project. In Meteor apps, this is done with the `public` directory in the app root. So, you can ask React Storybook to serve those static files. + +Here's how to tell React Storybook to use that directory to load static files: + +```sh +start-storybook -p 6977 -s ./public +``` -React Storybook is built on top of webpack. If you need, you can customize the webpack configurations used by React Storybook. +### Configuration Directory + +React Storybook uses `.storybook` directory as a default location for its [basic](#basic-configurations) and [custom webpack](#custom-webpack-configurations) configuration. + +Here's how to tell React Storybook to use a custom directory to load your configuration files: -We usually use this feature to add CSS support. +```sh +start-storybook -p 6977 -s ./public -c ./storybook-config +``` + +### Static Builder + +With Static Builder, you could convert your whole Storybook into a static site. Then, you can deploy that into any static site hosting service including "GitHub Pages". + +Add following script as an NPM script: + +```sh +build-storybook -o storybook-build-dir +``` + +Then it'll build and save a set of static files into the `storybook-build-dir` directory. You can access them by running a following python static server: + +```python +python -m SimpleHTTPServer +``` + +For more information, run `build-storybook -h`. + +## Custom Webpack Configurations + +React Storybook is built on top of Webpack. If you need, you can customize the Webpack configurations used by React Storybook. To do so, you need to create a file at `.storybook/webpack.config.js` and export a module like this: @@ -261,9 +166,13 @@ module.exports = { } ``` +### Add Custom CSS Loaders + +You can use this custom Webpack configurations to add css loaders. We've a [separate guide](/docs/setting_up_for_css.md) for that. + ### Customizing The UI -You can customize the UI by duplicating the original components such as [layout.js](https://raw.githubusercontent.com/kadirahq/react-storybook/master/src/client/ui/layout.js) file, put it in `.storybook/layout.js` and setting webpack config like this : +You can also customize the UI by duplicating the original components such as [layout.js](https://raw.githubusercontent.com/kadirahq/react-storybook/master/src/client/ui/layout.js) file, put it in `.storybook/layout.js` and setting webpack config like this : ```js const path = require('path'); @@ -280,13 +189,11 @@ module.exports = { } ``` -> You can pass options to this config file as you wish. But, there are some stuff like devServer we'll always add by default.
-> So, usually you need to use this config for doing following things: -> * for loading CSS, -> * for adding custom resolve extensions, -> * for adding resolve aliases. +### Other Configurations + +We allow you to use almost all [Webpack configurations](https://webpack.github.io/docs/configuration.html). So, you can customize as you wish. -## Load Custom HTML Head +## Load Custom HTML Head Content Sometimes, we need to load custom DOM nodes inside the HTML `` tag. For an example, this is how we can load TypeKit fonts with React Storybook. diff --git a/docs/guidelines.md b/docs/guidelines.md deleted file mode 100644 index bc8d0449c824..000000000000 --- a/docs/guidelines.md +++ /dev/null @@ -1,14 +0,0 @@ -# Guidelines for Creating Stories - -* Write UI components by passing data via props. In this way, you can isolate UI components easily. (Maybe you can follow a pattern like [Mantra](https://voice.kadira.io/sneak-peek-mantra-7161624acaa7).) -* Do not write app-specific code inside your UI components. -* Write your stories close to your UI components. A directory called `stories` inside your components directory is a good idea. -* In Meteor, you may need to use a directory name with `.stories` or create it inside the `tests` directory. Otherwise, these story files will be loaded by Meteor. -* In a single story module, create stories for a single component. -* Prefix story names with a dot (`.`). For example: - -```js -storiesOf('core.Button', module) -``` - -* Always use actions to debug event props (event handlers). diff --git a/docs/react-storybook-screenshot.png b/docs/react-storybook-screenshot.png deleted file mode 100644 index bc4a040f6ba8..000000000000 Binary files a/docs/react-storybook-screenshot.png and /dev/null differ diff --git a/docs/react-storybook-demo.gif b/docs/react_storybook_demo.gif similarity index 100% rename from docs/react-storybook-demo.gif rename to docs/react_storybook_demo.gif diff --git a/docs/react_storybook_screenshot.png b/docs/react_storybook_screenshot.png new file mode 100644 index 000000000000..9763382042b2 Binary files /dev/null and b/docs/react_storybook_screenshot.png differ diff --git a/docs/setting-up-for-css.md b/docs/setting_up_for_css.md similarity index 94% rename from docs/setting-up-for-css.md rename to docs/setting_up_for_css.md index a40b8e9c1235..574d6c6613f8 100644 --- a/docs/setting-up-for-css.md +++ b/docs/setting_up_for_css.md @@ -119,3 +119,8 @@ module.exports = { ``` > Click [here](https://github.com/mantrajs/mantra-sample-blog-app) to see a complete example. + +Refer following links to learn more about Meteor specific CSS configurations: + +* [#96](https://github.com/kadirahq/react-storybook/issues/96#issuecomment-211928389) +* [#20](https://github.com/kadirahq/react-storybook/issues/20) diff --git a/docs/writing_stories.md b/docs/writing_stories.md new file mode 100644 index 000000000000..baa4e7bdcbcf --- /dev/null +++ b/docs/writing_stories.md @@ -0,0 +1,155 @@ +# Writing Stories + +## TOC + +* [Basic API](#basic-api) +* [Creating Actions](#creating-actions) +* [Using Decorators](#using-decorators) +* [Linking Stories](#linking-stories) + +You need to write stories to show your components inside React Storybook. We've a set of APIs allows you to write stories and do more with them: + +## Basic API + +This is how you can create stories: + +```js +import React from 'react'; +import { storiesOf } from '@kadira/storybook'; + +storiesOf('Button', module) + .add('with a text', () => ( + + )) + .add('with no text', () => ( + + )); +``` + +When you are writing stories, you can follow these guidelines to write great stories. + +* Write UI components by passing data via props. In this way, you can isolate UI components easily. (Maybe you can follow a pattern like [Mantra](https://voice.kadira.io/sneak-peek-mantra-7161624acaa7).) +* Do not write app-specific code inside your UI components. +* Write your stories close to your UI components. A directory called `stories` inside your components directory is a good idea. +* In Meteor, you may need to use a directory name with `.stories` or create it inside the `tests` directory. Otherwise, these story files will be loaded by Meteor. +* In a single story module, create stories for a single component. +* Prefix story names with a dot (`.`). For example: + +```js +storiesOf('core.Button', module) +``` + +## Creating Actions + +Usually our components accept event handlers. Actions help us to debug those event handlers. These actions are logged in the `Action Logger` info window in React Storybook. + +This is how we can create an action: + +```js +import React from 'react'; +import { storiesOf, action } from '@kadira/storybook'; + +storiesOf('Button', module) + .add('with a text', () => ( + + )); +``` + +Here we create an action named `click the button`. It gives a function to the `onClick` prop in our button. + +Then, when you click on the button, it will log something like this into the Action Logger: + +```js +{ + "name": "click the button", + "args": [ + "[SyntheticEvent]", + ".1", + { + "isTrusted": false + } + ] +} +``` + +Here we can see the name we've mentioned when creating the action. After that, we can see the arguments passed to the `onClick` event handler. In this case, we've three arguments. `[SyntheticEvent]` is the actual event object passed by React and you can use that to get more details. + +> For simplicity, React Storybook does not show the actual object. Instead it will show `[SyntheticEvent]`. + +## Using Decorators + +In some apps, we need to wrap our components with a given context. Most of the time, you have to do this when you are using Material UI or Radium. + +So, you need to write your stories like this: + +```js +import React from 'react'; +import { storiesOf } from '@kadira/storybook'; +import Theme from '../theme'; +import MyComponent from '../my_component'; + +storiesOf('MyComponent', modules) + .add('without props', () => ( + + + + )) + .add('with some props', () => ( + + + + )); +``` + +As you can see, you always need to wrap your components with the `Theme` component. But, there's a much better way. See following example with a decorator: + +```js +import React from 'react'; +import { storiesOf } from '@kadira/storybook'; +import Theme from '../theme'; +import MyComponent from '../my_component'; + +storiesOf('MyComponent', modules) + .addDecorator((story) => ( + + {story()} + + )) + .add('without props', () => ()) + .add('with some props', () => ()); +``` + +You can add as many as decorators you want, but make sure to call `.addDecorator()` before you call `.add()`. + +## Linking Stories + +Sometimes, we may need to link stories. With that, we could use Storybook as a prototype builder. (like [InVision](https://www.invisionapp.com/), [Framer.js](http://framerjs.com/)). Here's how to do that. + +Let's say, we've a Toggle button and we need to change the story as we click the button. This is how we do it: + +```js +import { linkTo } from @kadira/storybook + +storiesOf('Toggle', module) + .add('on', () => { + return + }) + .add('off', () => { + return + }); +``` + +Have a look at the `linkTo` function: + +```js +linkTo('Toggle', 'off') +``` + +With that, you can link an event prop to any story in the Storybook. + +* First parameter is the the story kind name (what you named with `storiesOf`). +* Second parameter is the story name (what you named with `.add`). + +> You can also pass a function instead for any of above parameter. That function accepts arguments emitted by the event and it should return a string. + +Have a look at [PR86](https://github.com/kadirahq/react-storybook/pull/86) for more information.