Update headings in markdown for 6.0 docs

This commit is contained in:
domyen 2020-08-09 12:13:54 -04:00
parent 8ab84e761c
commit bdb83ae51b
14 changed files with 176 additions and 209 deletions

View File

@ -10,8 +10,6 @@ This is the core addon API. This is how to get the addon API:
import { addons } from '@storybook/addons';
```
Have a look at the API methods for more details:
### addons.getChannel()
Get an instance to the channel where you can communicate with the manager and the preview. You can find this in both the addon register code and in your addons wrapper component (where used inside a story).
@ -29,7 +27,7 @@ See how we can use this:
import { addons } from '@storybook/addons';
// Register the addon with a unique name.
addons.register('my-organisation/my-addon', api => {});
addons.register('my-organisation/my-addon', (api) => {});
```
Now you'll get an instance to our StorybookAPI. See the [api docs](#storybook-api) for Storybook API regarding using that.
@ -114,7 +112,7 @@ export const Panel = () => {
const state = useStorybookState();
return <div>do something with storybook's state</div>;
}
};
```
Allows full access to the entire storybook state.
@ -125,14 +123,13 @@ If you use this, remember your component wil be re-rendered a lot, and you may n
### useStorybookApi
```js
// my-addon/register.js
export const Panel = () => {
const state = useStorybookApi();
return <div>do something with storybook's api</div>;
}
};
```
Allows full access to the storybook API.
@ -155,7 +152,7 @@ export const Panel = () => {
clicking this will emit an event
</button>
);
}
};
```
Allows for both setting subscriptions to events and getting the emitter for emitting custom event unto the channel.
@ -170,21 +167,13 @@ The messages can be listened for on both the iframe and the manager side.
export const Panel = () => {
const [state, setState] = useAddonState('my/addon-id', 'initial state');
return (
<button onClick={() => setState('a new value')}>
the state = "{state}"
</button>
);
}
return <button onClick={() => setState('a new value')}>the state = "{state}"</button>;
};
export const Tool = () => {
const [state, setState] = useAddonState('my/addon-id', 'initial state');
return (
<button onClick={() => setState('a new value')}>
the state = "{state}"
</button>
);
}
return <button onClick={() => setState('a new value')}>the state = "{state}"</button>;
};
```
Extremely useful for addons that need to persist some state.
@ -209,7 +198,7 @@ export const Panel = () => {
{value}
</div>
);
}
};
```
This hook gets you the current story's parameter.
@ -247,7 +236,7 @@ This is how you can select the above story:
```js
// my-addon/register.js
addons.register('my-organisation/my-addon', api => {
addons.register('my-organisation/my-addon', (api) => {
api.selectStory('heading', 'withText');
});
```
@ -259,7 +248,7 @@ Same as `selectStory`, but accepts a story inside current kind as the only param
```js
// my-addon/register.js
addons.register('my-organisation/my-addon', api => {
addons.register('my-organisation/my-addon', (api) => {
api.selectInCurrentKind('withText');
});
```
@ -271,7 +260,7 @@ This method allows you to set query string parameters. You can use that as tempo
```js
// my-addon/register.js
addons.register('my-organisation/my-addon', api => {
addons.register('my-organisation/my-addon', (api) => {
api.setQueryParams({
abc: 'this is abc',
bbc: 'this is bbc',
@ -285,11 +274,10 @@ If you need to remove a query param, use `null` for that. For an example, let's
</div>
```js
// my-addon/register.js
addons.register('my-organisation/my-addon', api => {
addons.register('my-organisation/my-addon', (api) => {
api.setQueryParams({
bbc: null,
});
@ -301,7 +289,7 @@ addons.register('my-organisation/my-addon', api => {
This method allows you to get a query param set by above API `setQueryParams`. For example, let's say we need to get the bbc query param. Then this how we do it:
```jsx
addons.register('my-organisation/my-addon', api => {
addons.register('my-organisation/my-addon', (api) => {
api.getQueryParam('bbc');
});
```
@ -313,7 +301,7 @@ This method allows you to get application url state with some changed params. Fo
```js
// my-addon/register.js
addons.register('my-organisation/my-addon', api => {
addons.register('my-organisation/my-addon', (api) => {
const href = api.getUrlState({
selectedKind: 'kind',
selectedStory: 'story',
@ -328,7 +316,7 @@ This method allows you to register a handler function which will be called whene
```js
// my-addon/register.js
addons.register('my-organisation/my-addon', api => {
addons.register('my-organisation/my-addon', (api) => {
api.on('some-event', (eventData) => console.log(eventData));
});
```

View File

@ -8,6 +8,8 @@ NOTE: This API is experimental and may change outside of the typical semver rele
</div>
<br/>
ArgTypes are a first-class feature in Storybook for specifying the behaviour of [Args](../writing-stories/args.md). By specifying the type of an arg you constrain the values that it can take and can also provide information about args that are not explicitly set (i.e. not required).
You can also use argTypes to “annotate” args with information that is used by addons that make use of those args, for instance to instruct the controls addons to render a color choose for a string-valued arg.

View File

@ -2,8 +2,6 @@
title: 'Component Story Format (CSF)'
---
### Component Story Format (CSF)
Storybook's Component Story Format (CSF) is the recommended way to [write stories](../writing-stories/introduction.md) since Storybook 5.2. [Read the announcement](https://medium.com/storybookjs/component-story-format-66f4c32366df) to learn more about how it came to be.
<div style="background-color:#F8FAFC">
@ -20,7 +18,7 @@ In CSF, stories and component metadata are defined as ES Modules. Every componen
CSF is supported in all frameworks except React Native, where you should use the [storiesOf API](./storiesof.md) instead.
#### Default export
## Default export
The default export defines metadata about your component, including the `component` itself, its `title` (where it will show up in the [navigation UI story hierarchy](../writing-stories/docs/writing-stories/naming-components-and-hierarchy.md#sorting-stories)), [decorators](../writing-stories/decorators.md), and [parameters](../writing-stories/parameters.md).
@ -40,7 +38,7 @@ export default {
For more examples, see [writing stories](../writing-stories/introduction.md).
#### Named story exports
## Named story exports
With CSF, every named export in the file represents a story function by default.
@ -83,7 +81,7 @@ Simple.decorators = [ ... ];
Simple.parameters = { ... };
```
#### Args story inputs
## Args story inputs
Starting in SB 6.0, stories accept named inputs called Args. Args are dynamic data that are provided (and possibly updated by) Storybook and its addons.
@ -128,7 +126,7 @@ Not only are these versions shorter and easier to write than their no-args count
For more information on setting up [Docs](../writing-docs/introduction.md) and [Actions](../essentials/actions.md), see their respective documentation.
#### Storybook export vs name handling
## Storybook export vs name handling
Storybook handles named exports and `story.name` slightly differently. When should you use one vs. the other?
@ -161,7 +159,7 @@ You should use the `story.name` option in the following cases:
1. You want the name to show up in the Storybook UI in a way that's not possible with a named export, e.g. reserved keywords like "default", special characters like emoji, spacing/capitalization other than what's provided by `storyNameFromExport`.
2. You want to preserve the Story ID independently from changing how it's displayed. Having stable Story ID's is useful for integration with third party tools.
#### Non-story exports
## Non-story exports
In some cases, you may want to export a mixture of story and non-stories. For example, it can be useful to export data that's used in your stories.

View File

@ -2,11 +2,9 @@
title: 'MDX Format'
---
### MDX format
`MDX` is the syntax [Storybook Docs](../writing-docs/introduction.md) uses to capture long-form Markdown documentation and stories in one file. You can also write pure documentation pages in `MDX` and add them to Storybook alongside your stories. [Read the announcement](https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc) to learn more about how and why it came to be.
#### Basic example
## Basic example
Let's get started with an example that combines Markdown with a single story:
@ -30,6 +28,7 @@ With `MDX` we can define a story for `Checkbox` right in the middle of our Markd
</Story>
</Preview>
```
And here's how that's rendered in Storybook:
![Show a simple mdx example](./mdx-simple.png)
@ -38,7 +37,7 @@ As you can see there's a lot going on here. We're writing Markdown, we're writin
Let's break it down.
#### MDX-Flavored CSF
## MDX-Flavored CSF
[MDX](https://mdxjs.com/) is a standard file format that combines Markdown with JSX. This means you can use Markdowns terse syntax (such as `# heading`) for your documentation, and freely embed JSX component blocks at any point in the file.
@ -61,7 +60,7 @@ export const allCheckboxes = () => (
There's a one-to-one mapping from the code in `MDX` to `CSF`, which in turn directly corresponds to Storybook's internal `storiesOf` API. As a user, this means your existing Storybook knowledge should translate between the three. And technically, this means that the transformations that happen under the hood are simple and predictable.
#### Writing stories
## Writing stories
Now let's look at a more realistic example to see a few more things we can do:
@ -158,7 +157,7 @@ addDecorator(...);
addParameters({ ... });
```
#### Documentation-only MDX
## Documentation-only MDX
Typically, when you use Storybook MDX, you define stories in the MDX documentation is automatically associated with those stories. But what if you want to write Markdown-style documentation and have it show up in your Storybook?
@ -168,11 +167,9 @@ If you don't define a `Meta`, you can write Markdown and associate with an exist
To get a "documentation-only story", in your UI, define a `<Meta>` as you normally would, but don't define any stories. It will show up in your UI as a documentation node:
![Show documentation](./mdx-documentation-only.png)
### MDX file names
## MDX file names
Unless you use a custom webpack configuration, all of your `MDX` files should have the suffix `*.stories.mdx`. This tells Storybook to apply its special processing to the `<Meta>` and `<Story>` elements in the file.

View File

@ -2,7 +2,7 @@
title: 'Integration'
---
### Webpack
## Webpack
Storybook displays your components in a custom web application built using [webpack](https://webpack.js.org/). Webpack is a complex tool but our default configuration is intended to cover off the majority of use cases. There are also [addons](/addons) available that extend the configuration for other common use cases.
@ -10,27 +10,27 @@ You can customize Storybook's webpack setup by providing a `webpackFinal` field
The value should be an async function that receives a webpack config and eventually returns a webpack config.
#### Default configuration
### Default configuration
By default, Storybook's webpack configuration will allow you to:
- Import Images and other static files
You can import images and other local files and have them built into the Storybook:
You can import images and other local files and have them built into the Storybook:
```js
// This will include './static/image.png' in the bundle and return a path to be included in a src attribute
import imageFile from './static/image.png';
```
```js
// This will include './static/image.png' in the bundle and return a path to be included in a src attribute
import imageFile from './static/image.png';
```
- Import JSON as JavaScript
You can import `.json` files and have them expanded to a JavaScript object:
You can import `.json` files and have them expanded to a JavaScript object:
```js
// This will automatically be parsed to the contents of `data.json`
import data from './data.json';
```
```js
// This will automatically be parsed to the contents of `data.json`
import data from './data.json';
```
If you want to know the exact details of the webpack config, the best way is to run:
@ -38,7 +38,7 @@ If you want to know the exact details of the webpack config, the best way is to
yarn storybook --debug-webpack
```
#### Extending Storybooks webpack config
### Extending Storybooks webpack config
To extend the above configuration, use the `webpackFinal` field of [`.storybook/main.js`](./overview.md#configure-story-rendering).
@ -93,7 +93,7 @@ Finally, if your custom webpack config uses a loader that does not explicitly in
If you're using a non-standard Storybook config directory, you should put `main.js` there instead of `.storybook` and update the `include` path to make sure that it resolves to your project root.
#### Using your existing config
### Using your existing config
If you have an existing webpack config for your project and want to reuse this app's configuration, you can import your main webpack config into Storybook's [`.storybook/main.js`](./overview.md#configure-story-rendering) and merge both:
@ -113,13 +113,13 @@ module.exports = {
};
```
### Babel
## Babel
Storybooks webpack config by [default](#default-configuration) sets up [Babel](https://babeljs.io/) for ES6 transpiling. Storybook works with evergreen browsers and IE11 by default.
Here are some key features of Storybook's Babel configurations.
#### Default configuration
### Default configuration
We have added ES2016 support with Babel for transpiling your JS code.
@ -127,18 +127,17 @@ In addition to that, we've added a few additional features, like object spreadin
Check out our [source](https://github.com/storybookjs/storybook/blob/master/lib/core/src/server/common/babel.js) to learn more about these plugins.
#### Custom configuration
### Custom configuration
If your project has a `.babelrc` file, we'll use that instead of the default config file.
You can also place a `.storybook/.babelrc` file to use a special configuration for Storybook only.
### TypeScript
## TypeScript
Storybook has built-in Typescript support, so your Typescript project should work with zero configuration needed.
#### Default configuration
### Default configuration
The base Typescript configuration uses [`babel-loader`](https://webpack.js.org/loaders/babel-loader/) for Typescript transpilation, and optionally [`fork-ts-checker-webpack-plugin`](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) for checking.
@ -148,8 +147,7 @@ Each framework uses the base configuration unless otherwise specified:
- Vue ignores the base and uses `ts-loader` and applies it to both `.tsx` and `.vue` files.
- React adds `react-docgen-typescript-plugin` to the base.
#### Main.js configuration
### Main.js configuration
To make it easier to configure Typescript handling, use the `typescript` field in your [`.storybook/main.js`](./overview.md#configure-story-rendering).
@ -170,47 +168,44 @@ module.exports = {
};
```
|Field |Framework |Description |Type |
|:-------------------------------|:------------:|:---------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------:|
|**check** |All |optionally run fork-ts-checker-webpack-plugin |boolean |
|**checkOptions** |All |Options to pass to fork-ts-checker-webpack-plugin if it's enabled |[See docs](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) |
|**reactDocgen** |React |which variant docgen processor to run `'react-docgen-typescript' |N/A |
|**reactDocgenTypescriptOptions**|React |Options to pass to react-docgen-typescript-plugin if react-docgen-typescript is enabled. |[See docs](https://github.com/hipstersmoothie/react-docgen-typescript-plugin) |
| Field | Framework | Description | Type |
| :------------------------------- | :-------: | :--------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------: |
| **check** | All | optionally run fork-ts-checker-webpack-plugin | boolean |
| **checkOptions** | All | Options to pass to fork-ts-checker-webpack-plugin if it's enabled | [See docs](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) |
| **reactDocgen** | React | which variant docgen processor to run `'react-docgen-typescript' |N/A |
| **reactDocgenTypescriptOptions** | React | Options to pass to react-docgen-typescript-plugin if react-docgen-typescript is enabled. | [See docs](https://github.com/hipstersmoothie/react-docgen-typescript-plugin) |
### Styling and CSS
## Styling and CSS
There are many ways to include CSS in a web application, and correspondingly there are many ways to include CSS in Storybook. Usually it is best to try and replicate what your application does with styling in Storybooks configuration.
#### CSS-in-JS
### CSS-in-JS
CSS-in-JS libraries are designed to use basic JavaScript. They often work in Storybook without any extra configuration. Some libraries expect components to be rendered in a specific rendering “context” (for example, to provide themes) and you may need to add a [global decorator](../writing-stories/decorators.md#global-decorators) to supply it.
#### Importing CSS files
### Importing CSS files
If your component files import their own CSS, Storybooks webpack config will work unmodified with some exceptions:
- If you are using a CSS precompiler, you may need to add a preset (such as the [SCSS preset](https://github.com/storybookjs/presets/tree/master/packages/preset-scss), or add a loader to Storybooks webpack config).
- In Angular, you'll need to take special care how you handle CSS:
- Either [customize your webpack config](#extending-storybooks-webpack-config)
- Or use syntax to use a inline loader:
```js
import '!style-loader!css-loader!./styles.css';
```
- Either [customize your webpack config](#extending-storybooks-webpack-config)
- Or use syntax to use a inline loader:
```js
import '!style-loader!css-loader!./styles.css';
```
To use your CSS in all stories, you simply import it in [`.storybook/preview.js`](./overview.md#configure-story-rendering)
#### Adding webfonts
### Adding webfonts
If you need webfonts to be available, you may need to add some code to the [`.storybook/preview-head.html`](./story-rendering.md#adding-to-head) file. We recommend including any assets with your Storybook if possible, in which case you likely want to configure the [static file location](#serving-static-files-via-storybook).
### Images and assets
## Images and assets
Components often rely on images, videos, and other assets to render as the user expects. There are many ways to use these assets in your story files.
#### Import assets into stories
### Import assets into stories
You can import any media assets by importing (or requiring) them. This works out of the box with our default config. But, if you are using a custom webpack config, youll need to add the file-loader to handle the required files.
@ -231,23 +226,20 @@ const image = {
alt: 'my image',
};
export const withAnImage = () => (
<img src={image.src} alt={image.alt} />
);
export const withAnImage = () => <img src={image.src} alt={image.alt} />;
```
#### Serving static files via Storybook
### Serving static files via Storybook
We recommend serving static files via Storybook to ensure that your components always have the assets they need to load.
Configure a directory (or a list of directories) where your assets live when starting Storybook. Use the` -s` flag in your npm script like so:
Configure a directory (or a list of directories) where your assets live when starting Storybook. Use the`-s` flag in your npm script like so:
```json
{
"scripts": {
"start-storybook": "start-storybook -s ./public -p 9001"
}
"scripts": {
"start-storybook": "start-storybook -s ./public -p 9001"
}
}
```
@ -263,22 +255,20 @@ export default {
};
// assume image.png is located in the "public" directory.
export const withAnImage = () => (
<img src="/image.png" alt="my image" />
);
export const withAnImage = () => <img src="/image.png" alt="my image" />;
```
You can also pass a list of directories separated by commas without spaces instead of a single directory.
```json
{
"scripts": {
"start-storybook": "start-storybook -s ./public,./static -p 9001"
}
"scripts": {
"start-storybook": "start-storybook -s ./public,./static -p 9001"
}
}
```
#### Reference assets from a CDN
### Reference assets from a CDN
Upload your files to an online CDN and reference them. In this example were using a placeholder image service.
@ -297,8 +287,7 @@ export const withAnImage = () => (
);
```
#### Absolute versus relative paths
### Absolute versus relative paths
Sometimes, you may want to deploy your storybook into a subpath, like `https://example.com/storybook`.

View File

@ -10,7 +10,7 @@ Note you can change the folder that Storybook uses by setting the `-c` flag to y
</div>
### Configure your Storybook project
## Configure your Storybook project
The main configuration file is `main.js`. This file controls the behaviour of the Storybook server, and so you must restart Storybooks process when you change it. It contains the following:
@ -30,7 +30,7 @@ The `main.js` configuration file is a [preset](../api/presets.md) and as such ha
- `webpackFinal` - custom [webpack configuration](./integration.md#extending-storybooks-webpack-config).
- `babel` - custom [babel configuration](./integration.md#babel).
### Configure story loading
## Configure story loading
By default, Storybook will load stories from your project based on a glob (pattern matching string) in `.storybook/main.js` that matches all files in your project with extension `.stories.js`. The intention is you colocate a story file with the component it documents.
@ -53,7 +53,7 @@ module.exports = {
};
```
### Configure story rendering
## Configure story rendering
To control the way stories are rendered and add global [decorators](../writing-stories/decorators.md#global-decorators) and [parameters](../writing-stories/parameters.md#global-parameters), create a `.storybook/preview.js` file. This is loaded in the Canvas tab, the “preview” iframe that renders your components in isolation. Use `preview.js` for global code (such as [CSS imports](../get-started/setup.md#render-component-styles) or JavaScript mocks) that applies to all stories.
@ -65,7 +65,7 @@ The `preview.js` file can be an ES module and export the following keys:
If youre looking to change how your stories are ordered, read about [sorting stories](../writing-stories/naming-components-and-hierarchy.md#sorting-stories).
### Configure Storybooks UI
## Configure Storybooks UI
To control the behaviour of Storybooks UI (the **“manager”**), you can create a `.storybook/manager.js` file.

View File

@ -9,7 +9,7 @@ There are many ways to build pages in Storybook. Here are common patterns and so
- Pure presentational pages.
- Connected components (e.g. network requests, context, browser environment).
### Pure presentational pages
## Pure presentational pages
Teams at the BBC, The Guardian, and the Storybook maintainers themselves build pure presentational pages. If you take this approach, you don't need to do anything special to render your pages in Storybook.
@ -28,7 +28,7 @@ The downsides:
- It's less flexible if you want to load data incrementally in different places on the screen.
#### Args composition for presentational screens
### Args composition for presentational screens
When you are building screens in this way, it is typical that the inputs of a composite component are a combination of the inputs of the various sub-components it renders. For instance, if your screen renders a page layout (containing details of the current user), a header (describing the document you are looking at), and a list (of the subdocuments), the inputs of the screen may consist of the user, document and subdocuments.
@ -65,25 +65,25 @@ import DocumentList from './DocumentList.stories';
export default {
component: DocumentScreen,
title: 'DocumentScreen',
}
};
const Template = (args) => <DocumentScreen {...args} />;
export const Simple = Template.bind({});
Simple.args = {
user: PageLayout.Simple.user,
document: DocumentHeader.Simple.document,
subdocuments: DocumentList.Simple.documents,
user: PageLayout.Simple.user,
document: DocumentHeader.Simple.document,
subdocuments: DocumentList.Simple.documents,
};
```
This approach is particularly useful when the various subcomponents export a complex list of different stories, which you can pick and choose to build realistic scenarios for your screen-level stories without repeating yourself. By reusing the data and taking a Don't-Repeat-Yourself(DRY) philosophy, your story maintenance burden is minimal.
### Mocking connected components
## Mocking connected components
Render a connected component in Storybook by mocking the network requests that it makes to fetch its data. There are various layers in which you can do that.
#### Mocking providers
### Mocking providers
If you are using a provider that supplies data via the context, you can wrap your story in a decorator that supplies a mocked version of that provider. For example, in the [Screens](https://www.learnstorybook.com/intro-to-storybook/react/en/screen/) chapter of Learn Storybook we mock a Redux provider with mock data.
@ -106,7 +106,7 @@ LoggedOut.parameters: {
};
```
#### Mocking imports
### Mocking imports
It is also possible to mock imports directly, similar to Jest, using webpacks aliasing. This is extremely useful if your component makes network requests directly with third-party libraries.
@ -141,15 +141,15 @@ To use the mock in place of the real import, we use [webpack aliasing](https://w
module.exports = {
// your Storybook configuration
webpackFinal: config => {
webpackFinal: (config) => {
config.resolve.alias['isomorphic-fetch'] = require.resolve('../__mocks__/isomorphic-fetch.js');
return config;
}
},
};
```
Add the mock you've just implemented to your [storybook/preview.js](../configure/overview.md#configure-story-rendering) (if you don't have it already, you'll need to create the file):
```js
// .storybook/preview.js
import { decorator } from '../__mocks/isomorphic-fetch';
@ -191,9 +191,8 @@ Success.parameters = {
};
```
#### Specific mocks
### Specific mocks
Another mocking approach is to use libraries that intercept calls at a lower level. For instance you can use [`fetch-mock`](https://www.npmjs.com/package/fetch-mock) to mock fetch requests specifically, or [`msw`](https://www.npmjs.com/package/msw) to mock all kinds of network traffic.
Similar to the import mocking above, once you have a mock youll still want to set the return value of the mock on a per-story basis. Do this in Storybook with a decorator that reads story parameters.

View File

@ -1,5 +1,5 @@
---
title: 'Interaction testing'
title: 'Interaction testing with Storybook'
---
Stories are useful for verifying the known states of a component. But sometimes you need to test how a component changes in response to user interaction.
@ -19,5 +19,3 @@ describe('My Component', () => {
});
})
```

View File

@ -6,13 +6,13 @@ Storybook is widely used by component libraries and design systems. Design syste
For example, if you use a design system package, its stories can appear alongside your own. That makes it convenient to cross reference usage documentation without leaving Storybook.
### For package consumers
## For package consumers
Composition happens automatically if the package [supports](#for-package-authors) it. When you install the package, Storybook will load its stories alongside your own.
![Package composition workflow](./package-composition.png)
#### Configuring
### Configuring
If you want to configure how the composed Storybook behaves, you can disable the `ref` element in your [`.storybook/main.js`](../configure/overview.md#configure-story-rendering)
@ -26,29 +26,28 @@ module.exports = {
}
```
#### Changing versions
### Changing versions
Change the version of the composed Storybook to see how the library evolves. This requires [configuration](#providing-a-version-section) from the package author.
![Package composition workflow](./composition-versioning.png)
### For package authors
## For package authors
Component library authors can expand adoption by composing their components in their consumers Storybooks.
Add a `storybook` property in your published `package.json `that contains an object with a `url` field. Point the URL field to a published Storybook at the version you want.
Add a `storybook` property in your published `package.json`that contains an object with a `url` field. Point the URL field to a published Storybook at the version you want.
```json
// Your component librarys package.json
{
"storybook": {
"url": "https://host.com/your-storybook-for-this-version"
}
"storybook": {
"url": "https://host.com/your-storybook-for-this-version"
}
}
```
#### Automatic version selection
### Automatic version selection
If you are using a [CHP level 1 service](#chp-level-1) for hosting (such as [Chromatic.com](https://www.chromatic.com/)), you can provide a single URL for your Storybook in the `storybook.url` field. You do not need to change the URL each time you publish a new version. Storybook will automatically find the correct URL for your package.
@ -56,23 +55,23 @@ For example, for Chromatic, you might do:
```json
{
"storybook": {
"url": "https://master--xyz123.chromatic.com"
}
"storybook": {
"url": "https://master--xyz123.chromatic.com"
}
}
```
In this example `xyz123` is your projects id. Storybook will automatically compose in the Storybook published to that project corresponding to the version the user has installed.
#### Providing a version section
### Providing a version section
Similarly, if you're using a [CHP level 1 service](#chp-level-1) (such as chromatic.com) for hosting, you can provide a list of versions for the user to [choose from](#changing-versions) to experiment with other versions of your package.
### Component Hosting Protocol (CHP)
## Component Hosting Protocol (CHP)
Storybook can communicate with services that host built Storybooks online. This enables features such as [Composition](./storybook-composition). We categorize services via compliance with the "Component Hosting Protocol" (CHP) with various levels of support in Storybook.
#### CHP level 1
### CHP level 1
<div style="background-color:#F8FAFC">
TODO: "version=x.y.z query parameter".(vet this)
@ -85,12 +84,14 @@ The service serves uploaded Storybooks and makes the following available:
- Support for /metadata.json and the releases field.
Examples of such services:
- [chromatic.com](https://www.chromatic.com/)
#### CHP level 0
### CHP level 0
The service can serve uploaded Storybooks. There is no special integration with Storybook APIs.
Examples of such services:
- [Netlify](https://www.netlify.com/)
- [S3](https://aws.amazon.com/en/s3/)

View File

@ -4,7 +4,7 @@ title: 'Publish Storybook'
Storybook is more than a UI component development tool. Teams also publish Storybook online to review and collaborate on works in progress. That allows developers, designers, and PMs to check if UI looks right without touching code or needing a local dev environment.
### Build Storybook as a static web application
## Build Storybook as a static web application
First, well need to build Storybook as a static web application using `build-storybook`, a command thats installed by default.
@ -24,11 +24,9 @@ Asides from the `-o` flag, you can also include other flags to build Storybook,
You can learn more about these flag options [here](../api/cli-options.md).
</div>
### Publish Storybook online
## Publish Storybook online
Once your Storybook is built as a static web app it can be deployed to any static site hosting services. The Storybook team uses [Chromatic](https://www.chromatic.com/), a free publishing service made by Storybook maintainers that documents, versions, and indexes your UI components securely in the cloud.
@ -41,7 +39,7 @@ We also maintain [`storybook-deployer`](https://github.com/storybookjs/storybook
/>
</video>
### Review with your team
## Review with your team
Publishing Storybook as part of the development process makes it quick and easy to [gather team feedback](https://www.learnstorybook.com/design-systems-for-developers/react/en/review/).
@ -51,7 +49,7 @@ If you publish your Storybook to Chromatic, you can use the [UI Review](https://
![Storybook publishing workflow](./workflow-publish.png)
### Reference external Storybooks
## Reference external Storybooks
Storybook allows you to browse components from any [Storybook published online](./storybook-composition.md) inside your local Storybook. It unlocks common workflows that teams often struggle with:
@ -59,7 +57,6 @@ Storybook allows you to browse components from any [Storybook published online](
- 🎨 Design systems can expand adoption by composing themselves into their users Storybooks.
- 🛠 Frontend platform can audit how components are used across projects.
![Storybook reference external](./reference-external-storybooks-composition.jpg)
Toggle between multiple versions of Storybook to see how components change between versions. This is useful for design system package authors who maintain many versions at once.

View File

@ -1,17 +1,11 @@
---
title: 'Snapshot testing'
title: 'Snapshot testing with Storybook'
---
Snapshot tests compare the rendered markup of every story against known baselines. Its an easy way to identify markup changes that trigger rendering errors and warnings.
Storybook is a convenient tool for snapshot testing because every story is essentially a test specification. Any time you write or update a story you get a snapshot test for free.
<div class="aside">
Snapshot vs visual tests. [Visual tests](./visual-testing.md) take screenshots of stories and compare them against known baselines. When used to test appearance, visual tests are often a more robust solution than snapshot tests because verifying markup doesnt test for visual changes.
</div>
Storyshots is an [official addon](https://github.com/storybookjs/storybook/tree/master/addons/storyshots/storyshots-core) that enables snapshot testing. Its powered by Jest so youll need to [install that](https://jestjs.io/docs/en/getting-started) first. Continue on if you already have Jest.
Install the addon. **Make sure** the version of Storyshots and your projects Storybook version are identical.
@ -62,3 +56,9 @@ When you make changes to your components or stories, run the test again to ident
If the changes are intentional we can accept them as new baselines. If the changes are bugs, fix the underlying code then run the snapshot tests again.
Storyshots has many options for advanced use cases; read more in the [addons documentation](https://github.com/storybookjs/storybook/tree/master/addons/storyshots/storyshots-core).
<div class="aside">
Snapshot vs visual tests. [Visual tests](./visual-testing.md) take screenshots of stories and compare them against known baselines. When used to test appearance, visual tests are often a more robust solution than snapshot tests because verifying markup doesnt test for visual changes.
</div>

View File

@ -24,6 +24,7 @@ export const OneItem = (args) => (
</List>
);
```
Note that by adding `subcomponents` to the default export, we get an extra pane on the ArgsTable, listing the props of `ListItem`:
![Storybook story with subcomponent argstable](./argstable-subcomponents.png)
@ -35,7 +36,7 @@ The downside of the above approach is that it does not take advantage of Storybo
Let's talk about some techniques you can use to mitigate the above, which are especially useful in more complicated situations.
### Reusing subcomponent stories
## Reusing subcomponent stories
The simplest change we can make to the above is to reuse the stories of the `ListItem` in the `List`:
@ -57,25 +58,24 @@ By rendering the `Unchecked` story with its args, we are able to reuse the input
However, we still arent using args to control the `ListItem` stories, which means we cannot change them with controls and we cannot reuse them in other, more complex component stories.
### Using children as an arg
## Using children as an arg
One way we improve that situation is by pulling the render subcomponent out into a `children` arg:
```js
// List.story.js
const Template = (args) => <List {...args} />
const Template = (args) => <List {...args} />;
export const OneItem = Template.bind({});
OneItem.args = {
children: <Unchecked {...Unchecked.args} />
}
children: <Unchecked {...Unchecked.args} />,
};
```
Now that `children` is an arg, we can potentially reuse it in another story. As things stand (we hope to improve this soon) you cannot edit children in a control yet.
### Creating a Template Component
## Creating a Template Component
Another option that is more “data”-based is to create a special “story-generating” template component:
@ -89,7 +89,9 @@ import { Unchecked } from './ListItem.stories';
const ListTemplate = ({ items, ...args }) => (
<List>
{items.map(item => <ListItem {...item} />)}
{items.map((item) => (
<ListItem {...item} />
))}
</List>
);

View File

@ -2,15 +2,13 @@
title: 'Storybook Composition'
---
Composition allows you to embed components from any Storybook inside your local Storybook.
Its made for teams who adopt Storybook in multiple projects but cant ensure that the projects have the same tech stack or share the same repo.
Composition allows you to embed components from any Storybook inside your local Storybook. Its made for teams who adopt Storybook in multiple projects but cant ensure that the projects have the same tech stack or share the same repo.
You can compose any Storybook [published online](./publish-storybook.md) or running locally no matter the view layer, tech stack, or dependencies.
![Storybook composition](./combine-storybooks.png)
### Compose published Storybooks
## Compose published Storybooks
In your [`storybook/main.js`](../configure/overview.md#configure-story-rendering) file add a `refs` field with information about the reference Storybook. Pass in a URL to a statically built Storybook.
@ -27,27 +25,25 @@ module.exports={
}
```
### Compose local Storybooks
## Compose local Storybooks
You can also compose Storybook that are running locally. For instance, if you have a React Storybook and a Angular Storybook running on different ports:
```js
//.storybook/main.js
module.exports={
module.exports = {
// your Storybook configuration
refs: {
react: {
title: "React",
url: 'http://localhost:7007'
title: 'React',
url: 'http://localhost:7007',
},
angular: {
title: "Angular",
url: 'http://localhost:7008'
}
}
}
title: 'Angular',
url: 'http://localhost:7008',
},
},
};
```
This composes the React and Angular Storybooks into your current Storybook. When either code base changes, hot-module-reload will work perfectly. That enables you to develop both frameworks in sync.

View File

@ -6,12 +6,6 @@ Visual tests, also called visual regression tests, catch bugs in UI appearance.
This is ideal for verifying what the user sees: layout, color, size, and contrast. Storybook is a fantastic tool for visual testing because every story is essentially a test specification. Any time you write or update a story you get a spec for free.
<div class="aside">
Visual vs snapshot tests. [Snapshot tests](./snapshot-testing.md) compare the rendered markup of every story against known baselines. When used to test how things look, snapshot tests generate a lot of false positives because code changes dont always yield visual changes.
</div>
![Visually testing a component in Storybook](./component-visual-testing.gif)
There are [many tools](https://github.com/mojoaxel/awesome-regression-testing) for visual testing. Storybook uses [Chromatic](https://www.chromatic.com), a visual testing service made by Storybook maintainers to run tests in the cloud across browsers.
@ -19,3 +13,9 @@ There are [many tools](https://github.com/mojoaxel/awesome-regression-testing) f
This prevents UI bugs in [Storybook itself](https://www.chromatic.com/library?appId=5a375b97f4b14f0020b0cda3), the [design system](https://www.chromatic.com/library?appId=5ccbc373887ca40020446347), and our [website](https://www.chromatic.com/library?appId=5be26744d2f6250024a9117d).
We also maintain [StoryShots](https://github.com/storybookjs/storybook/tree/master/addons/storyshots), a snapshot testing addon that integrates with [jest-image-snapshot](https://github.com/storybookjs/storybook/tree/master/addons/storyshots#configure-storyshots-for-image-snapshots).
<div class="aside">
Visual vs snapshot tests. [Snapshot tests](./snapshot-testing.md) compare the rendered markup of every story against known baselines. When used to test how things look, snapshot tests generate a lot of false positives because code changes dont always yield visual changes.
</div>