mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-31 05:03:21 +08:00
Merge branch 'next' into fix/valid-globs
# Conflicts: # MIGRATION.md
This commit is contained in:
commit
540d0a2119
@ -43,7 +43,7 @@ module.exports = {
|
||||
overrides: [
|
||||
{
|
||||
test: './examples/vue-kitchen-sink',
|
||||
presets: ['babel-preset-vue'],
|
||||
presets: ['@vue/babel-preset-jsx'],
|
||||
env: {
|
||||
test: withTests,
|
||||
},
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,3 +31,4 @@ cypress/videos
|
||||
cypress/screenshots
|
||||
examples/ember-cli/ember-output
|
||||
.verdaccio-cache
|
||||
tsconfig.tsbuildinfo
|
||||
|
51
CHANGELOG.md
51
CHANGELOG.md
@ -1,3 +1,54 @@
|
||||
## 6.0.0-beta.14 (May 25, 2020)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- CSF: Hoist story annotation object ([#10907](https://github.com/storybookjs/storybook/pull/10907))
|
||||
- Vue: Remove babel-preset-vue ([#10909](https://github.com/storybookjs/storybook/pull/10909))
|
||||
|
||||
### Features
|
||||
|
||||
- Angular: Support `workspace.json` in nx workspace ([#10881](https://github.com/storybookjs/storybook/pull/10881))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Addon-docs: Fix single item width in Preview block ([#10877](https://github.com/storybookjs/storybook/pull/10877))
|
||||
- UI: Center toolbar icon buttons ([#10897](https://github.com/storybookjs/storybook/pull/10897))
|
||||
- Core: Fix double rendering on startup ([#10892](https://github.com/storybookjs/storybook/pull/10892))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Core: Use dedicated loader for es6 modules ([#10783](https://github.com/storybookjs/storybook/pull/10783))
|
||||
- Core: Fix yarn test command on windows ([#10904](https://github.com/storybookjs/storybook/pull/10904))
|
||||
|
||||
## 5.3.19 (May 24, 2020)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- UI: Fix search stories ([#10539](https://github.com/storybookjs/storybook/pull/10539))
|
||||
|
||||
### Security
|
||||
|
||||
- Upgrade markdown-to-jsx to 6.11.4 ([#10873](https://github.com/storybookjs/storybook/pull/10873))
|
||||
|
||||
## 6.0.0-beta.13 (May 23, 2020)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Core: Fix ts/tsx resolution in the manager ([#10886](https://github.com/storybookjs/storybook/pull/10886))
|
||||
- Core: Fix typo in projectRoot node_modules detection ([#10848](https://github.com/storybookjs/storybook/pull/10848))
|
||||
- Addon-docs: Fix story inline rendering ([#10875](https://github.com/storybookjs/storybook/pull/10875))
|
||||
- Core: Fix CRA filter for built-in webpack settings ([#10861](https://github.com/storybookjs/storybook/pull/10861))
|
||||
- Addon-docs: Fix react forwardRefs with destructured props ([#10864](https://github.com/storybookjs/storybook/pull/10864))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- React: Upgrade preset-create-react-app in examples ([#10867](https://github.com/storybookjs/storybook/pull/10867))
|
||||
- Core: Close server when e2e test failed ([#10868](https://github.com/storybookjs/storybook/pull/10868))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
- Upgrade markdown-to-jsx to 6.11.4 ([#10873](https://github.com/storybookjs/storybook/pull/10873))
|
||||
|
||||
## 6.0.0-beta.12 (May 21, 2020)
|
||||
|
||||
### Breaking Changes
|
||||
|
67
MIGRATION.md
67
MIGRATION.md
@ -1,6 +1,7 @@
|
||||
<h1>Migration</h1>
|
||||
|
||||
- [From version 5.3.x to 6.0.x](#from-version-53x-to-60x)
|
||||
- [Hoisted CSF annotations](#hoisted-csf-annotations)
|
||||
- [Zero config typescript](#zero-config-typescript)
|
||||
- [Correct globs in main.js](#correct-globs-in-main-js)
|
||||
- [Backgrounds addon has a new api](#backgrounds-addon-has-a-new-api)
|
||||
@ -15,6 +16,7 @@
|
||||
- [Imported types](#imported-types)
|
||||
- [Rolling back](#rolling-back)
|
||||
- [New addon presets](#new-addon-presets)
|
||||
- [Removed babel-preset-vue from Vue preset](#removed-babel-preset-vue-from-vue-preset)
|
||||
- [Removed Deprecated APIs](#removed-deprecated-apis)
|
||||
- [New setStories event](#new-setstories-event)
|
||||
- [Client API changes](#client-api-changes)
|
||||
@ -115,6 +117,48 @@
|
||||
|
||||
## From version 5.3.x to 6.0.x
|
||||
|
||||
### Hoisted CSF annotations
|
||||
|
||||
Storybook 6 introduces hoisted CSF annotations and deprecates the `StoryFn.story` object-style annotation.
|
||||
|
||||
In 5.x CSF, you would annotate a story like this:
|
||||
|
||||
```js
|
||||
export const Basic = () => <Button />
|
||||
Basic.story = {
|
||||
name: 'foo',
|
||||
parameters: { ... },
|
||||
decorators: [ ... ],
|
||||
};
|
||||
```
|
||||
|
||||
In 6.0 CSF this becomes:
|
||||
|
||||
```js
|
||||
export const Basic = () => <Button />
|
||||
Basic.storyName = 'foo';
|
||||
Basic.parameters = { ... };
|
||||
Basic.decorators = [ ... ];
|
||||
```
|
||||
|
||||
1. The new syntax is slightly more compact/ergonomic compared the the old one
|
||||
2. Similar to React's `displayName`, `propTypes`, `defaultProps` annotations
|
||||
3. We're introducing a new feature, [Storybook Args](https://docs.google.com/document/d/1Mhp1UFRCKCsN8pjlfPdz8ZdisgjNXeMXpXvGoALjxYM/edit?usp=sharing), where the new syntax will be significantly more ergonomic
|
||||
|
||||
To help you upgrade your stories, we've crated a codemod:
|
||||
|
||||
```
|
||||
npx @storybook/cli@next migrate csf-hoist-story-annotations --glob="**/*.stories.js"
|
||||
```
|
||||
|
||||
For more information, [see the documentation](https://github.com/storybookjs/storybook/blob/next/lib/codemod/README.md#csf-hoist-story-annotations).
|
||||
|
||||
### Zero config typescript
|
||||
|
||||
Storybook has built-in Typescript support in 6.0. That means you should remove your complex Typescript configurations from your `.storybook` config. We've tried to pick sensible defaults that work out of the box, especially for nice prop table generation in `@storybook/addon-docs`.
|
||||
|
||||
To migrate from an old setup, we recommend deleting any typescript-specific webpack/babel configurations in your project. If you want to override the defaults, see the [typescript configuration docs](https://github.com/storybookjs/storybook/blob/next/docs/src/pages/configurations/typescript-config/index.md).
|
||||
|
||||
### Correct globs in main.js
|
||||
|
||||
In 5.3 we introduced the `main.js` file with an `stories` property. This property was documented as a "glob" pattern. This was our intention, however the implementation allowed for non valid globs to be specified and work. In fact we promoted invalid globs in our documentation and CLI templates.
|
||||
@ -133,12 +177,6 @@ Example of an **valid** glob:
|
||||
stories: ['./**/*.stories.@(ts|js)']
|
||||
```
|
||||
|
||||
### Zero config typescript
|
||||
|
||||
Storybook has built-in Typescript support in 6.0. That means you should remove your complex Typescript configurations from your `.storybook` config. We've tried to pick sensible defaults that work out of the box, especially for nice prop table generation in `@storybook/addon-docs`.
|
||||
|
||||
To migrate from an old setup, we recommend deleting any typescript-specific webpack/babel configurations in your project. If you want to override the defaults, see the [typescript configuration docs](https://github.com/storybookjs/storybook/blob/next/docs/src/pages/configurations/typescript-config/index.md).
|
||||
|
||||
### Backgrounds addon has a new api
|
||||
|
||||
Starting in 6.0, the backgrounds addon now receives an object instead of an array as parameter, with a property to define the default background.
|
||||
@ -361,6 +399,23 @@ MyNonCheckedStory.story = {
|
||||
};
|
||||
```
|
||||
|
||||
### Removed babel-preset-vue from Vue preset
|
||||
|
||||
`babel-preset-vue` is not included by default anymore when using Storybook with Vue.
|
||||
This preset is outdated and [caused problems](https://github.com/storybookjs/storybook/issues/4475) with more modern setups.
|
||||
|
||||
If you have an older Vue setup that relied on this preset, make sure it is included in your babel config
|
||||
(install `babel-preset-vue` and add it to the presets).
|
||||
|
||||
```json
|
||||
{
|
||||
"presets": ["babel-preset-vue"]
|
||||
}
|
||||
```
|
||||
|
||||
However, please take a moment to review why this preset is necessary in your setup.
|
||||
One usecase used to be to enable JSX in your stories. For this case, we recommend to use `@vue/babel-preset-jsx` instead.
|
||||
|
||||
### Removed Deprecated APIs
|
||||
|
||||
In 6.0 we removed a number of APIs that were previously deprecated.
|
||||
|
@ -40,10 +40,8 @@ If you wish to selectively disable `a11y` checks for a subset of stories, you ca
|
||||
|
||||
```js
|
||||
export const MyNonCheckedStory = () => <SomeComponent />;
|
||||
MyNonCheckedStory.story = {
|
||||
parameters: {
|
||||
a11y: { disable: true },
|
||||
},
|
||||
MyNonCheckedStory.parameters = {
|
||||
a11y: { disable: true },
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-a11y",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "a11y addon for storybook",
|
||||
"keywords": [
|
||||
"a11y",
|
||||
@ -33,14 +33,14 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/channels": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/channels": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"axe-core": "^3.5.2",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-actions",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Action Logger addon for storybook",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -28,12 +28,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -20,15 +20,16 @@ Add the following content to it:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
addons: ['@storybook/addon-backgrounds']
|
||||
}
|
||||
addons: ['@storybook/addon-backgrounds'],
|
||||
};
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Backgrounds requires two parameters:
|
||||
* `default` - matches the **name** of the value which will be selected by default.
|
||||
* `values` - an array of elements containing name and value (with a valid css color e.g. HEX, RGBA, etc.)
|
||||
Backgrounds requires two parameters:
|
||||
|
||||
- `default` - matches the **name** of the value which will be selected by default.
|
||||
- `values` - an array of elements containing name and value (with a valid css color e.g. HEX, RGBA, etc.)
|
||||
|
||||
Write your stories like this:
|
||||
|
||||
@ -37,7 +38,7 @@ import React from 'react';
|
||||
|
||||
/*
|
||||
* Button.stories.js
|
||||
* Applies backgrounds to the Stories
|
||||
* Applies backgrounds to the Stories
|
||||
*/
|
||||
export default {
|
||||
title: 'Button',
|
||||
@ -52,9 +53,7 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const defaultView = () => (
|
||||
<button>Click me</button>
|
||||
);
|
||||
export const defaultView = () => <button>Click me</button>;
|
||||
```
|
||||
|
||||
You can add the backgrounds to all stories by using `parameters` in `.storybook/preview.js`:
|
||||
@ -78,42 +77,35 @@ import React from 'react';
|
||||
|
||||
export default {
|
||||
title: 'Button',
|
||||
}
|
||||
};
|
||||
|
||||
export const defaultView = () => (
|
||||
<button>Click me</button>
|
||||
);
|
||||
export const defaultView = () => <button>Click me</button>;
|
||||
|
||||
defaultView.story = {
|
||||
parameters: {
|
||||
backgrounds: {
|
||||
default: 'red',
|
||||
values: [
|
||||
{ name: 'red', value: 'rgba(255, 0, 0)' },
|
||||
],
|
||||
},
|
||||
}
|
||||
defaultView.parameters = {
|
||||
backgrounds: {
|
||||
default: 'red',
|
||||
values: [{ name: 'red', value: 'rgba(255, 0, 0)' }],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Once you have defined backgrounds for your stories (as can be seen in the examples above), you can set a default background per story by passing the `default` property using a name from the available backgrounds:
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
|
||||
/*
|
||||
* Button.stories.js
|
||||
* Applies default background to the Stories
|
||||
* Applies default background to the Stories
|
||||
*/
|
||||
export default {
|
||||
title: 'Button',
|
||||
parameters: {
|
||||
backgrounds: { default: 'twitter' },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export const twitterColorSelected = () => (
|
||||
<button>Click me</button>
|
||||
);
|
||||
export const twitterColorSelected = () => <button>Click me</button>;
|
||||
```
|
||||
|
||||
If you don't want to use backgrounds for a story, you can set the `backgrounds` parameter to `{ disable: true }` to skip the addon:
|
||||
@ -123,19 +115,15 @@ import React from 'react';
|
||||
|
||||
/*
|
||||
* Button.stories.js
|
||||
* Disables backgrounds for one Story
|
||||
* Disables backgrounds for one Story
|
||||
*/
|
||||
export default {
|
||||
title: 'Button',
|
||||
}
|
||||
};
|
||||
|
||||
export const disabledBackgrounds = () => (
|
||||
<button>Click me</button>
|
||||
);
|
||||
export const disabledBackgrounds = () => <button>Click me</button>;
|
||||
|
||||
disabledBackgrounds.story = {
|
||||
parameters: {
|
||||
backgrounds: { disable: true },
|
||||
},
|
||||
disabledBackgrounds.parameters = {
|
||||
backgrounds: { disable: true },
|
||||
};
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-backgrounds",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "A storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -32,12 +32,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"memoizerific": "^1.11.3",
|
||||
"react": "^16.8.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-cssresources",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "A storybook addon to switch between css resources at runtime for your story",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -32,11 +32,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-design-assets",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Design asset preview for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -34,12 +34,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -226,12 +226,7 @@ addParameters({
|
||||
|
||||
## TypeScript configuration
|
||||
|
||||
SB Docs for React uses `babel-plugin-react-docgen` to extract Docgen comments from your code automatically. However, if you're using TypeScript, some extra configuration maybe required to get this information included in your docs.
|
||||
|
||||
1. You can add [react-docgen-typescript-loader](https://www.npmjs.com/package/react-docgen-typescript-loader) to your project by following the instructions there.
|
||||
2. You can use [@storybook/preset-typescript](https://www.npmjs.com/package/@storybook/preset-typescript) which includes `react-docgen-typescript-loader`.
|
||||
|
||||
Install the preset with care. If you've already configured Typescript manually, that configuration may conflict with the preset. You can [debug your final webpack configuration with `--debug-webpack`](https://storybook.js.org/docs/configurations/custom-webpack-config/#debug-the-default-webpack-config).
|
||||
As of SB6 [TypeScript is zero-config](https://github.com/storybookjs/storybook/blob/next/docs/src/pages/configurations/typescript-config/index.md) and should work with SB Docs out of the box. For advanced configuration options, refer to the [Props documentation](./docs/props-tables.md).
|
||||
|
||||
## More resources
|
||||
|
||||
|
@ -12,6 +12,7 @@ To learn more about Storybook Docs, read the [general documentation](../README.m
|
||||
|
||||
- [Installation](#installation)
|
||||
- [DocsPage](#docspage)
|
||||
- [Props tables](#props-tables)
|
||||
- [MDX](#mdx)
|
||||
- [IFrame height](#iframe-height)
|
||||
- [More resources](#more-resources)
|
||||
@ -36,7 +37,9 @@ module.exports = {
|
||||
|
||||
When you [install docs](#installation) you should get basic [DocsPage](../docs/docspage.md) documentation automagically for all your stories, available in the `Docs` tab of the Storybook UI.
|
||||
|
||||
Props tables for your components requires a few more steps. Docs for Angular relies on [Compodoc](https://compodoc.app/), the excellent API documentation tool. It supports `inputs`, `outputs`, `properties`, `methods`, `view/content child/children` as first class prop types.
|
||||
## Props tables
|
||||
|
||||
Getting [Props tables](../docs/props-tables.md) for your components requires a few more steps. Docs for Angular relies on [Compodoc](https://compodoc.app/), the excellent API documentation tool. It supports `inputs`, `outputs`, `properties`, `methods`, `view/content child/children` as first class prop types.
|
||||
|
||||
To get this, you'll first need to install Compodoc:
|
||||
|
||||
@ -192,8 +195,8 @@ For `DocsPage`, you need to update the parameter locally in a story:
|
||||
|
||||
```ts
|
||||
export const basic = () => ...
|
||||
basic.story = {
|
||||
parameters: { docs: { iframeHeight: 400 } }
|
||||
basic.parameters = {
|
||||
docs: { iframeHeight: 400 }
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -80,8 +80,8 @@ For `DocsPage`, you need to update the parameter locally in a story:
|
||||
|
||||
```ts
|
||||
export const basic = () => ...
|
||||
basic.story = {
|
||||
parameters: { docs: { iframeHeight: 400 } }
|
||||
basic.parameters = {
|
||||
docs: { iframeHeight: 400 }
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -110,8 +110,8 @@ export default {
|
||||
import { Button } from './Button';
|
||||
// export default { ... }
|
||||
export const basic => () => <Button>Basic</Button>
|
||||
basic.story = {
|
||||
parameters: { docs: { page: null } }
|
||||
basic.parameters = {
|
||||
docs: { page: null }
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -7,20 +7,13 @@
|
||||
Storybook Docs automatically generates props tables for components in supported frameworks. This document is a consolidated summary of prop tables, provides instructions for reporting bugs, and list known limitations for each framework.
|
||||
|
||||
- [Usage](#usage)
|
||||
- [Args Controls](#args-controls)
|
||||
- [Controls](#controls)
|
||||
- [DocsPage](#docspage)
|
||||
- [MDX](#mdx)
|
||||
- [Controls customization](#controls-customization)
|
||||
- [Rows customization](#rows-customization)
|
||||
- [Reporting a bug](#reporting-a-bug)
|
||||
- [Known limitations](#known-limitations)
|
||||
- [React](#react)
|
||||
- [Fully support React.FC](#fully-support-reactfc)
|
||||
- [Imported types](#imported-types)
|
||||
- [Vue](#vue)
|
||||
- [Angular](#angular)
|
||||
- [Web components](#web-components)
|
||||
- [Ember](#ember)
|
||||
- [More resources](#more-resources)
|
||||
|
||||
## Usage
|
||||
@ -52,9 +45,9 @@ import { MyComponent } from './MyComponent';
|
||||
<Props of={MyComponent} />
|
||||
```
|
||||
|
||||
## Args Controls
|
||||
## Controls
|
||||
|
||||
Starting in SB 6.0, the `Props` block has built-in controls (formerly known as "knobs") for editing stories dynamically.
|
||||
Starting in SB 6.0, the `Props` block has built-in `Controls` (formerly known as "knobs") for editing stories dynamically.
|
||||
|
||||
<center>
|
||||
<img src="./media/args-controls.gif" width="100%" />
|
||||
@ -155,20 +148,18 @@ export const Batch = ({ labels, padding }) => (
|
||||
In this case, the args are basically unrelated to the underlying component's props, and are instead related to the individual story. To generate a prop table for the story, you can configure the Story's metadata:
|
||||
|
||||
```js
|
||||
Batch.story = {
|
||||
argTypes: {
|
||||
labels: {
|
||||
description: 'A comma-separated list of labels to display',
|
||||
defaultValue: 'a,b,c',
|
||||
control: { type: 'array' }
|
||||
}
|
||||
padding: {
|
||||
description: 'The padding to space out labels int he story',
|
||||
defaultValue: 4,
|
||||
control: { type: 'range', min: 0, max: 20, step: 2 },
|
||||
}
|
||||
}
|
||||
}
|
||||
Batch.argTypes = {
|
||||
labels: {
|
||||
description: 'A comma-separated list of labels to display',
|
||||
defaultValue: 'a,b,c',
|
||||
control: { type: 'array' },
|
||||
},
|
||||
padding: {
|
||||
description: 'The padding to space out labels int he story',
|
||||
defaultValue: 4,
|
||||
control: { type: 'range', min: 0, max: 20, step: 2 },
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
In this case, the user-specified `argTypes` are not a subset of the component's props, so Storybook shows ONLY the user-specified `argTypes`, and shows the component's props (without controls) in a separate tab.
|
||||
@ -197,57 +188,13 @@ If the problem appears to be an issue with the sub-package, please file an issue
|
||||
|
||||
This package relies on a variety of sub-packages to extract property information from components. Many of the bugs in this package correspond to bugs in a sub-package. Since we don't maintain the sub-packages, the best we can do for now is (1) document these limitations, (2) provide clean reproductions to the sub-package, (3) optionally provide PRs to those packages to fix the problems.
|
||||
|
||||
### React
|
||||
|
||||
SB Docs for React uses `babel-plugin-react-docgen`/`react-docgen` for both JS PropTypes prop tables and, as of 6.0, TypeScript-driven props tables.
|
||||
|
||||
#### Fully support React.FC
|
||||
|
||||
The biggest known issue is https://github.com/reactjs/react-docgen/issues/387, which means that the following common pattern **DOESN'T WORK**:
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
interface IProps { ... };
|
||||
const MyComponent: FC<IProps> = ({ ... }) => ...
|
||||
```
|
||||
|
||||
The following workaround is needed:
|
||||
|
||||
```tsx
|
||||
const MyComponent: FC<IProps> = ({ ... }: IProps) => ...
|
||||
```
|
||||
|
||||
Please upvote https://github.com/reactjs/react-docgen/issues/387 if this is affecting your productivity, or better yet, submit a fix!
|
||||
|
||||
#### Imported types
|
||||
|
||||
Another major issue is support for imported types.
|
||||
|
||||
```js
|
||||
import React, { FC } from 'react';
|
||||
import SomeType from './someFile';
|
||||
|
||||
type NewType = SomeType & { foo: string };
|
||||
const MyComponent: FC<NewType> = ...
|
||||
```
|
||||
|
||||
This was also an issue in RDTL so it doesn't get worse with `react-docgen`. There's an open PR for this https://github.com/reactjs/react-docgen/pull/352 which you can upvote if it affects you.
|
||||
|
||||
### Vue
|
||||
|
||||
SB Docs for Vue uses `vue-docgen-loader`/`vue-docgen-api` for SFC and JSX components.
|
||||
|
||||
### Angular
|
||||
|
||||
SB Docs for Angular uses `compodoc` for prop table information.
|
||||
|
||||
### Web components
|
||||
|
||||
SB Docs for Web-components uses `custom-elements.json` for prop table information.
|
||||
|
||||
### Ember
|
||||
|
||||
SB Docs for Ember uses `yui-doc` for prop table information.
|
||||
| Framework | Underlying library | Docs | Open issues |
|
||||
| -------------- | ---------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| React | `react-docgen` `react-docgen-typescript` | [Docs](../react/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+react%22) |
|
||||
| Vue | `vue-docgen-api` | [Docs](../vue/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+vue%22) |
|
||||
| Angular | `compodoc` | [Docs](../angular/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+angular%22) |
|
||||
| Web-components | `custom-elements.json` | [Docs](../web-components/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+web-components%22) |
|
||||
| Ember | `yui-doc` | [Docs](../ember/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+ember%22) |
|
||||
|
||||
## More resources
|
||||
|
||||
|
@ -51,8 +51,8 @@ export default {
|
||||
};
|
||||
|
||||
export const basic = () => <Button>Basic</Button>;
|
||||
basic.story = {
|
||||
parameters: { foo: 'bar' },
|
||||
basic.parameters = {
|
||||
foo: 'bar',
|
||||
};
|
||||
```
|
||||
|
||||
@ -199,7 +199,7 @@ User defines stories in CSF and renders docs using DocsPage, but wishes to exclu
|
||||
|
||||
```js
|
||||
export const foo = () => <Button>foo</Button>;
|
||||
foo.story = { parameters: { docs: { disable: true } } };
|
||||
foo.parameters = { docs: { disable: true } };
|
||||
```
|
||||
|
||||
### MDX Stories
|
||||
@ -220,11 +220,9 @@ Based on user feedback, it's also possible to control the view mode for an indiv
|
||||
|
||||
```js
|
||||
export const Foo = () => <Component />;
|
||||
Foo.story = {
|
||||
parameters: {
|
||||
// reset the view mode to "story" whenever the user navigates to this story
|
||||
viewMode: 'story',
|
||||
},
|
||||
Foo.parameters = {
|
||||
// reset the view mode to "story" whenever the user navigates to this story
|
||||
viewMode: 'story',
|
||||
};
|
||||
```
|
||||
|
||||
@ -245,10 +243,8 @@ If you override the `docs.source.code` parameter, the `Source` block will render
|
||||
|
||||
```js
|
||||
const Example = () => <Button />;
|
||||
Example.story = {
|
||||
parameters: {
|
||||
docs: { source: { code: 'some arbitrary string' } },
|
||||
},
|
||||
Example.parameters = {
|
||||
docs: { source: { code: 'some arbitrary string' } },
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -8,6 +8,7 @@ To learn more about Storybook Docs, read the [general documentation](../README.m
|
||||
|
||||
- [Installation](#installation)
|
||||
- [DocsPage](#docspage)
|
||||
- [Props tables](#props-tables)
|
||||
- [MDX](#mdx)
|
||||
- [IFrame height](#iframe-height)
|
||||
- [More resources](#more-resources)
|
||||
@ -32,7 +33,9 @@ module.exports = {
|
||||
|
||||
When you [install docs](#installation) you should get basic [DocsPage](../docs/docspage.md) documentation automagically for all your stories, available in the `Docs` tab of the Storybook UI.
|
||||
|
||||
Props tables for your components requires a few more steps. Docs for Ember relies on [@storybook/ember-cli-storybook addon](https://github.com/storybookjs/ember-cli-storybook), to extract documentation comments from your component source files. If you're using Storybook with Ember, you should already have this addon installed, you will just need to enable it by adding the following config block in your `ember-cli-build.js` file:
|
||||
## Props tables
|
||||
|
||||
Getting [Props tables](../docs/props-tables.md) for your components requires a few more steps. Docs for Ember relies on [@storybook/ember-cli-storybook addon](https://github.com/storybookjs/ember-cli-storybook), to extract documentation comments from your component source files. If you're using Storybook with Ember, you should already have this addon installed, you will just need to enable it by adding the following config block in your `ember-cli-build.js` file:
|
||||
|
||||
```js
|
||||
let app = new EmberApp(defaults, {
|
||||
@ -131,8 +134,8 @@ For `DocsPage`, you need to update the parameter locally in a story:
|
||||
|
||||
```ts
|
||||
export const basic = () => ...
|
||||
basic.story = {
|
||||
parameters: { docs: { iframeHeight: 400 } }
|
||||
basic.parameters = {
|
||||
docs: { iframeHeight: 400 }
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-docs",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Superior documentation for your components",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -48,17 +48,17 @@
|
||||
"@mdx-js/loader": "^1.5.1",
|
||||
"@mdx-js/mdx": "^1.5.1",
|
||||
"@mdx-js/react": "^1.5.1",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/csf": "0.0.1",
|
||||
"@storybook/node-logger": "6.0.0-beta.12",
|
||||
"@storybook/postinstall": "6.0.0-beta.12",
|
||||
"@storybook/source-loader": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/node-logger": "6.0.0-beta.14",
|
||||
"@storybook/postinstall": "6.0.0-beta.14",
|
||||
"@storybook/source-loader": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"acorn": "^7.1.0",
|
||||
"acorn-jsx": "^5.1.0",
|
||||
"acorn-walk": "^7.0.0",
|
||||
@ -84,8 +84,8 @@
|
||||
"@babel/core": "^7.9.6",
|
||||
"@emotion/core": "^10.0.20",
|
||||
"@emotion/styled": "^10.0.17",
|
||||
"@storybook/react": "6.0.0-beta.12",
|
||||
"@storybook/web-components": "6.0.0-beta.12",
|
||||
"@storybook/react": "6.0.0-beta.14",
|
||||
"@storybook/web-components": "6.0.0-beta.14",
|
||||
"@types/cross-spawn": "^6.0.1",
|
||||
"@types/doctrine": "^0.0.3",
|
||||
"@types/enzyme": "^3.10.3",
|
||||
|
@ -12,8 +12,10 @@ To learn more about Storybook Docs, read the [general documentation](../README.m
|
||||
|
||||
- [Installation](#installation)
|
||||
- [DocsPage](#docspage)
|
||||
- [Props tables](#props-tables)
|
||||
- [MDX](#mdx)
|
||||
- [Inline Stories](#inline-stories)
|
||||
- [Inline stories](#inline-stories)
|
||||
- [TypeScript props with `react-docgen`](#typescript-props-with-react-docgen)
|
||||
- [More resources](#more-resources)
|
||||
|
||||
## Installation
|
||||
@ -37,7 +39,9 @@ module.exports = {
|
||||
|
||||
When you [install docs](#installation) you should get basic [DocsPage](../docs/docspage.md) documentation automagically for all your stories, available in the `Docs` tab of the Storybook UI.
|
||||
|
||||
To show the props table for your component, be sure to fill in the `component` field in your story metadata:
|
||||
## Props tables
|
||||
|
||||
Storybook Docs automatically generates [Props tables](../docs/props-tables.md) for your components based on either `PropTypes` or `TypeScript` types. To show the props table for your component, be sure to fill in the `component` field in your story metadata:
|
||||
|
||||
```ts
|
||||
import { Button } from './Button';
|
||||
@ -98,7 +102,7 @@ Some **markdown** description, or whatever you want.
|
||||
<Props of={Button} />
|
||||
```
|
||||
|
||||
## Inline Stories
|
||||
## Inline stories
|
||||
|
||||
Storybook Docs renders all React stories inline on the page by default. If you want to render stories in an `iframe` so that they are better isolated. To do this, update `.storybook/preview.js`:
|
||||
|
||||
@ -112,6 +116,66 @@ addParameters({
|
||||
});
|
||||
```
|
||||
|
||||
## TypeScript props with `react-docgen`
|
||||
|
||||
If you're using TypeScript, there are two different options for generating props: `react-docgen-typescript` (default) or `react-docgen`.
|
||||
|
||||
You can add the following lines to your `.storybook/main.js` to switch between the two (or disable docgen):
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
typescript: {
|
||||
// also valid 'react-docgen-typescript' | false
|
||||
reactDocgen: 'react-docgen',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Neither option is perfect, so here's everything you should know if you're thinking about using `react-docgen` for TypeScript.
|
||||
|
||||
| | `react-docgen-typescript` | `react-docgen` |
|
||||
| --------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| **Features** | **Great**. The analysis produces great results which gives the best props table experience. | **OK**. React-docgen produces basic results that are fine for most use cases. |
|
||||
| **Performance** | **Slow**. It's doing a lot more work to produce those results, and may also have an inefficient implementation. | **Blazing fast**. Adding it to your project increases build time negligibly. |
|
||||
| **Bugs** | **Many**. There are a lot of corner cases that are not handled properly, and are annoying for developers. | **Few**. But there's a dealbreaker, which is lack for imported types (see below). |
|
||||
| **SB docs** | **Good**. Our prop tables have supported `react-docgen-typescript` results from the beginning, so it's relatively stable. | **OK**. There are some obvious improvements to fully support `react-docgen`, and they're coming soon. |
|
||||
|
||||
**Performance** is a common question, so here are build times from a random project to quantify. Your mileage may vary:
|
||||
|
||||
| Docgen | Build time |
|
||||
| ----------------------- | ---------- |
|
||||
| react-docgen-typescript | 59s |
|
||||
| react-docgen | 29s |
|
||||
| none | 28s |
|
||||
|
||||
The biggest limitation of `react-docgen` is lack of support for imported types. What that means is that when a component uses a type defined in another file or package, `react-docgen` is unable to extract props information for that type.
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import SomeType from './someFile';
|
||||
|
||||
type NewType = SomeType & { foo: string };
|
||||
const MyComponent: FC<NewType> = ...
|
||||
```
|
||||
|
||||
So in the previous example, `SomeType` would simply be ignored! There's an [open PR for this in the `react-docgen` repo](https://github.com/reactjs/react-docgen/pull/352) which you can upvote if it affects you.
|
||||
|
||||
Another common pitfall when switching to `react-docgen` is [lack of support for `React.FC`](https://github.com/reactjs/react-docgen/issues/387). This means that the following common pattern **DOESN'T WORK**:
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
interface IProps { ... };
|
||||
const MyComponent: FC<IProps> = ({ ... }) => ...
|
||||
```
|
||||
|
||||
Fortunately, the following workaround works:
|
||||
|
||||
```tsx
|
||||
const MyComponent: FC<IProps> = ({ ... }: IProps) => ...
|
||||
```
|
||||
|
||||
Please upvote [the issue](https://github.com/reactjs/react-docgen/issues/387) if this is affecting your productivity, or better yet, submit a fix!
|
||||
|
||||
## More resources
|
||||
|
||||
Want to learn more? Here are some more articles on Storybook Docs:
|
||||
|
@ -49,9 +49,8 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const componentNotes = () => <Button>Component notes</Button>;
|
||||
componentNotes.story = {};
|
||||
componentNotes.story.name = 'component notes';
|
||||
componentNotes.story.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
componentNotes.storyName = 'component notes';
|
||||
componentNotes.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
|
@ -33,9 +33,8 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const componentNotes = () => <Button>Component notes</Button>;
|
||||
componentNotes.story = {};
|
||||
componentNotes.story.name = 'component notes';
|
||||
componentNotes.story.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
componentNotes.storyName = 'component notes';
|
||||
componentNotes.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
|
@ -52,10 +52,9 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const one = () => <Button>One</Button>;
|
||||
one.story = {};
|
||||
one.story.name = 'one';
|
||||
one.story.parameters = { storySource: { source: '<Button>One</Button>' } };
|
||||
one.story.decorators = [(storyFn) => <div className=\\"local\\">{storyFn()}</div>];
|
||||
one.storyName = 'one';
|
||||
one.parameters = { storySource: { source: '<Button>One</Button>' } };
|
||||
one.decorators = [(storyFn) => <div className=\\"local\\">{storyFn()}</div>];
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
|
@ -38,7 +38,7 @@ export const __page = () => {
|
||||
throw new Error('Docs-only story');
|
||||
};
|
||||
|
||||
__page.story = { parameters: { docsOnly: true } };
|
||||
__page.parameters = { docsOnly: true };
|
||||
|
||||
const componentMeta = { title: 'docs-only', includeStories: ['__page'] };
|
||||
|
||||
|
@ -32,7 +32,7 @@ export const __page = () => {
|
||||
throw new Error('Docs-only story');
|
||||
};
|
||||
|
||||
__page.story = { parameters: { docsOnly: true } };
|
||||
__page.parameters = { docsOnly: true };
|
||||
|
||||
const componentMeta = { title: \\"Addons/Docs/what's in a title?\\", includeStories: ['__page'] };
|
||||
|
||||
|
@ -40,14 +40,12 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const one = () => <Button>One</Button>;
|
||||
one.story = {};
|
||||
one.story.name = 'one';
|
||||
one.story.parameters = { storySource: { source: '<Button>One</Button>' } };
|
||||
one.storyName = 'one';
|
||||
one.parameters = { storySource: { source: '<Button>One</Button>' } };
|
||||
|
||||
export const helloStory = () => <Button>Hello button</Button>;
|
||||
helloStory.story = {};
|
||||
helloStory.story.name = 'hello story';
|
||||
helloStory.story.parameters = { storySource: { source: '<Button>Hello button</Button>' } };
|
||||
helloStory.storyName = 'hello story';
|
||||
helloStory.parameters = { storySource: { source: '<Button>Hello button</Button>' } };
|
||||
|
||||
const componentMeta = { title: 'Button', includeStories: ['one', 'helloStory'] };
|
||||
|
||||
|
@ -49,14 +49,12 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const componentNotes = () => <Button>Component notes</Button>;
|
||||
componentNotes.story = {};
|
||||
componentNotes.story.name = 'component notes';
|
||||
componentNotes.story.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
componentNotes.storyName = 'component notes';
|
||||
componentNotes.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
|
||||
export const storyNotes = () => <Button>Story notes</Button>;
|
||||
storyNotes.story = {};
|
||||
storyNotes.story.name = 'story notes';
|
||||
storyNotes.story.parameters = {
|
||||
storyNotes.storyName = 'story notes';
|
||||
storyNotes.parameters = {
|
||||
storySource: { source: '<Button>Story notes</Button>' },
|
||||
...{
|
||||
notes: 'story notes',
|
||||
|
@ -53,14 +53,12 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const helloButton = () => <Button>Hello button</Button>;
|
||||
helloButton.story = {};
|
||||
helloButton.story.name = 'hello button';
|
||||
helloButton.story.parameters = { storySource: { source: '<Button>Hello button</Button>' } };
|
||||
helloButton.storyName = 'hello button';
|
||||
helloButton.parameters = { storySource: { source: '<Button>Hello button</Button>' } };
|
||||
|
||||
export const two = () => <Button>Two</Button>;
|
||||
two.story = {};
|
||||
two.story.name = 'two';
|
||||
two.story.parameters = { storySource: { source: '<Button>Two</Button>' } };
|
||||
two.storyName = 'two';
|
||||
two.parameters = { storySource: { source: '<Button>Two</Button>' } };
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
|
@ -49,9 +49,8 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const componentNotes = () => <Button>Component notes</Button>;
|
||||
componentNotes.story = {};
|
||||
componentNotes.story.name = 'component notes';
|
||||
componentNotes.story.argTypes = {
|
||||
componentNotes.storyName = 'component notes';
|
||||
componentNotes.argTypes = {
|
||||
a: {
|
||||
name: 'A',
|
||||
},
|
||||
@ -59,11 +58,11 @@ componentNotes.story.argTypes = {
|
||||
name: 'B',
|
||||
},
|
||||
};
|
||||
componentNotes.story.args = {
|
||||
componentNotes.args = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
componentNotes.story.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
componentNotes.parameters = { storySource: { source: '<Button>Component notes</Button>' } };
|
||||
|
||||
const componentMeta = { title: 'Button', includeStories: ['componentNotes'] };
|
||||
|
||||
|
@ -33,9 +33,8 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const text = () => 'Plain text';
|
||||
text.story = {};
|
||||
text.story.name = 'text';
|
||||
text.story.parameters = { storySource: { source: \\"'Plain text'\\" } };
|
||||
text.storyName = 'text';
|
||||
text.parameters = { storySource: { source: \\"'Plain text'\\" } };
|
||||
|
||||
const componentMeta = { title: 'Text', includeStories: ['text'] };
|
||||
|
||||
|
@ -43,24 +43,20 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const one = () => <Button>One</Button>;
|
||||
one.story = {};
|
||||
one.story.name = 'one';
|
||||
one.story.parameters = { storySource: { source: '<Button>One</Button>' } };
|
||||
one.storyName = 'one';
|
||||
one.parameters = { storySource: { source: '<Button>One</Button>' } };
|
||||
|
||||
export const helloStory = () => <Button>Hello button</Button>;
|
||||
helloStory.story = {};
|
||||
helloStory.story.name = 'hello story';
|
||||
helloStory.story.parameters = { storySource: { source: '<Button>Hello button</Button>' } };
|
||||
helloStory.storyName = 'hello story';
|
||||
helloStory.parameters = { storySource: { source: '<Button>Hello button</Button>' } };
|
||||
|
||||
export const wPunctuation = () => <Button>with punctuation</Button>;
|
||||
wPunctuation.story = {};
|
||||
wPunctuation.story.name = 'w/punctuation';
|
||||
wPunctuation.story.parameters = { storySource: { source: '<Button>with punctuation</Button>' } };
|
||||
wPunctuation.storyName = 'w/punctuation';
|
||||
wPunctuation.parameters = { storySource: { source: '<Button>with punctuation</Button>' } };
|
||||
|
||||
export const _1FineDay = () => <Button>starts with number</Button>;
|
||||
_1FineDay.story = {};
|
||||
_1FineDay.story.name = '1 fine day';
|
||||
_1FineDay.story.parameters = { storySource: { source: '<Button>starts with number</Button>' } };
|
||||
_1FineDay.storyName = '1 fine day';
|
||||
_1FineDay.parameters = { storySource: { source: '<Button>starts with number</Button>' } };
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
|
@ -37,9 +37,8 @@ function MDXContent({ components, ...props }) {
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const basic = assertIsFn(basicFn);
|
||||
basic.story = {};
|
||||
basic.story.name = 'basic';
|
||||
basic.story.parameters = { storySource: { source: 'basicFn' } };
|
||||
basic.storyName = 'basic';
|
||||
basic.parameters = { storySource: { source: 'basicFn' } };
|
||||
|
||||
const componentMeta = { title: 'story-function-var', includeStories: ['basic'] };
|
||||
|
||||
|
@ -39,9 +39,8 @@ export const functionStory = () => {
|
||||
btn.addEventListener('click', action('Click'));
|
||||
return btn;
|
||||
};
|
||||
functionStory.story = {};
|
||||
functionStory.story.name = 'function';
|
||||
functionStory.story.parameters = {
|
||||
functionStory.storyName = 'function';
|
||||
functionStory.parameters = {
|
||||
storySource: {
|
||||
source:
|
||||
\\"() => {\\\\n const btn = document.createElement('button');\\\\n btn.innerHTML = 'Hello Button';\\\\n btn.addEventListener('click', action('Click'));\\\\n return btn;\\\\n}\\",
|
||||
|
@ -39,9 +39,8 @@ export const multipleChildren = () => (
|
||||
<p>Hello Child #2</p>
|
||||
</>
|
||||
);
|
||||
multipleChildren.story = {};
|
||||
multipleChildren.story.name = 'multiple children';
|
||||
multipleChildren.story.parameters = {
|
||||
multipleChildren.storyName = 'multiple children';
|
||||
multipleChildren.parameters = {
|
||||
storySource: { source: '<p>Hello Child #1</p>\\\\n<p>Hello Child #2</p>' },
|
||||
};
|
||||
|
||||
|
@ -51,9 +51,8 @@ export const toStorybook = () => ({
|
||||
declarations: [Welcome],
|
||||
},
|
||||
});
|
||||
toStorybook.story = {};
|
||||
toStorybook.story.name = 'to storybook';
|
||||
toStorybook.story.parameters = {
|
||||
toStorybook.storyName = 'to storybook';
|
||||
toStorybook.parameters = {
|
||||
storySource: {
|
||||
source:
|
||||
'{\\\\n template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`,\\\\n props: {\\\\n showApp: linkTo(\\\\'Button\\\\')\\\\n },\\\\n moduleMetadata: {\\\\n declarations: [Welcome]\\\\n }\\\\n}',
|
||||
|
@ -33,7 +33,7 @@ export const __page = () => {
|
||||
throw new Error('Docs-only story');
|
||||
};
|
||||
|
||||
__page.story = { parameters: { docsOnly: true } };
|
||||
__page.parameters = { docsOnly: true };
|
||||
|
||||
const componentMeta = { title: \`\${titleFunction('template')}\`, includeStories: ['__page'] };
|
||||
|
||||
|
@ -102,16 +102,15 @@ function genStoryExport(ast, context) {
|
||||
}
|
||||
|
||||
statements.push(`export const ${storyKey} = ${storyVal};`);
|
||||
statements.push(`${storyKey}.story = {};`);
|
||||
|
||||
// always preserve the name, since CSF exports can get modified by displayName
|
||||
statements.push(`${storyKey}.story.name = '${storyName}';`);
|
||||
statements.push(`${storyKey}.storyName = '${storyName}';`);
|
||||
|
||||
const argTypes = genAttribute('argTypes', ast.openingElement);
|
||||
if (argTypes) statements.push(`${storyKey}.story.argTypes = ${argTypes};`);
|
||||
if (argTypes) statements.push(`${storyKey}.argTypes = ${argTypes};`);
|
||||
|
||||
const args = genAttribute('args', ast.openingElement);
|
||||
if (args) statements.push(`${storyKey}.story.args = ${args};`);
|
||||
if (args) statements.push(`${storyKey}.args = ${args};`);
|
||||
|
||||
let parameters = getAttr(ast.openingElement, 'parameters');
|
||||
parameters = parameters && parameters.expression;
|
||||
@ -119,16 +118,16 @@ function genStoryExport(ast, context) {
|
||||
const sourceParam = `storySource: { source: '${source}' }`;
|
||||
if (parameters) {
|
||||
const { code: params } = generate(parameters, {});
|
||||
statements.push(`${storyKey}.story.parameters = { ${sourceParam}, ...${params} };`);
|
||||
statements.push(`${storyKey}.parameters = { ${sourceParam}, ...${params} };`);
|
||||
} else {
|
||||
statements.push(`${storyKey}.story.parameters = { ${sourceParam} };`);
|
||||
statements.push(`${storyKey}.parameters = { ${sourceParam} };`);
|
||||
}
|
||||
|
||||
let decorators = getAttr(ast.openingElement, 'decorators');
|
||||
decorators = decorators && decorators.expression;
|
||||
if (decorators) {
|
||||
const { code: decos } = generate(decorators, {});
|
||||
statements.push(`${storyKey}.story.decorators = ${decos};`);
|
||||
statements.push(`${storyKey}.decorators = ${decos};`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
@ -336,7 +335,7 @@ function extractExports(node, options) {
|
||||
if (metaExport) {
|
||||
if (!storyExports.length) {
|
||||
storyExports.push('export const __page = () => { throw new Error("Docs-only story"); };');
|
||||
storyExports.push('__page.story = { parameters: { docsOnly: true } };');
|
||||
storyExports.push('__page.parameters = { docsOnly: true };');
|
||||
includeStories.push('__page');
|
||||
}
|
||||
} else {
|
||||
|
@ -13,6 +13,7 @@ To learn more about Storybook Docs, read the [general documentation](../README.m
|
||||
- [Installation](#installation)
|
||||
- [Preset options](#preset-options)
|
||||
- [DocsPage](#docspage)
|
||||
- [Props tables](#props-tables)
|
||||
- [MDX](#mdx)
|
||||
- [Inline Stories](#inline-stories)
|
||||
- [More resources](#more-resources)
|
||||
@ -62,7 +63,9 @@ The `vueDocgenOptions` is an object for configuring `vue-docgen-api`. See [`vue-
|
||||
|
||||
When you [install docs](#installation) you should get basic [DocsPage](../docs/docspage.md) documentation automagically for all your stories, available in the `Docs` tab of the Storybook UI.
|
||||
|
||||
Props tables for your components requires a few more steps. Docs for Vue relies on [`vue-docgen-loader`](https://github.com/pocka/vue-docgen-loader). It supports `props`, `events`, and `slots` as first class prop types.
|
||||
## Props tables
|
||||
|
||||
Getting [Props tables](../docs/props-tables.md) for your components requires a few more steps. Docs for Vue relies on [`vue-docgen-loader`](https://github.com/pocka/vue-docgen-loader). It supports `props`, `events`, and `slots` as first class prop types.
|
||||
|
||||
Finally, be sure to fill in the `component` field in your story metadata:
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
# Storybook Docs for Web Components
|
||||
<h1>Storybook Docs for Web Components</h1>
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Props tables](#props-tables)
|
||||
- [Stories not inline](#stories-not-inline)
|
||||
- [More resources](#more-resources)
|
||||
|
||||
## Installation
|
||||
|
||||
@ -22,9 +27,9 @@
|
||||
};
|
||||
```
|
||||
|
||||
### custom-elements.json
|
||||
## Props tables
|
||||
|
||||
In order to get documentation for web-components you will need to have a [custom-elements.json](https://github.com/webcomponents/custom-elements-json) file.
|
||||
In order to get [Props tables](..docs/../../docs/props-tables.md) documentation for web-components you will need to have a [custom-elements.json](https://github.com/webcomponents/custom-elements-json) file.
|
||||
|
||||
You can hand write it or better generate it. Depending on the web components sugar you are choosing your milage may vary.
|
||||
|
||||
@ -44,7 +49,7 @@ To generate this file with Stencil, add `docs-vscode` to outputTargets in `stenc
|
||||
},
|
||||
```
|
||||
|
||||
The file looks somewthing like this:
|
||||
The file looks something like this:
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-essentials",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Curated addons to bring out the best of Storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,13 +28,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addon-actions": "6.0.0-beta.12",
|
||||
"@storybook/addon-backgrounds": "6.0.0-beta.12",
|
||||
"@storybook/addon-docs": "6.0.0-beta.12",
|
||||
"@storybook/addon-viewport": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/node-logger": "6.0.0-beta.12",
|
||||
"@storybook/addon-actions": "6.0.0-beta.14",
|
||||
"@storybook/addon-backgrounds": "6.0.0-beta.14",
|
||||
"@storybook/addon-docs": "6.0.0-beta.14",
|
||||
"@storybook/addon-viewport": "6.0.0-beta.14",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/node-logger": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"ts-dedent": "^1.1.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-events",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Add events to your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -31,11 +31,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"format-json": "^1.0.3",
|
||||
"lodash": "^4.17.15",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-google-analytics",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook addon for google analytics",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -20,8 +20,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react-ga": "^2.5.7",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-graphql",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook addon to display the GraphiQL IDE",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -31,8 +31,8 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-transform-classes": "^7.9.2",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@types/webpack": "^4.41.9",
|
||||
"babel-loader": "^8.0.6",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -73,8 +73,8 @@ within `.storybook/main.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
addons: ['@storybook/addon-jest']
|
||||
}
|
||||
addons: ['@storybook/addon-jest'],
|
||||
};
|
||||
```
|
||||
|
||||
## Usage
|
||||
@ -92,13 +92,9 @@ export default {
|
||||
decorators: [withTests({ results })],
|
||||
};
|
||||
|
||||
export const defaultView = () => (
|
||||
<div>Jest results in storybook</div>
|
||||
);
|
||||
defaultView.story = {
|
||||
parameters: {
|
||||
jest: ['MyComponent.test.js', 'MyOtherComponent.test.js'],
|
||||
},
|
||||
export const defaultView = () => <div>Jest results in storybook</div>;
|
||||
defaultView.parameters = {
|
||||
jest: ['MyComponent.test.js', 'MyOtherComponent.test.js'],
|
||||
};
|
||||
```
|
||||
|
||||
@ -126,13 +122,9 @@ export default {
|
||||
title: 'MyComponent',
|
||||
};
|
||||
|
||||
export const defaultView = () => (
|
||||
<div>Jest results in storybook</div>
|
||||
);
|
||||
defaultView.story = {
|
||||
parameters: {
|
||||
jest: ['MyComponent.test.js', 'MyOtherComponent.test.js'],
|
||||
},
|
||||
export const defaultView = () => <div>Jest results in storybook</div>;
|
||||
defaultView.parameters = {
|
||||
jest: ['MyComponent.test.js', 'MyOtherComponent.test.js'],
|
||||
};
|
||||
```
|
||||
|
||||
@ -147,13 +139,9 @@ export default {
|
||||
title: 'MyComponent',
|
||||
};
|
||||
|
||||
export const defaultView = () => (
|
||||
<div>Jest results in storybook</div>
|
||||
);
|
||||
defaultView.story = {
|
||||
parameters: {
|
||||
jest: { disable: true },
|
||||
},
|
||||
export const defaultView = () => <div>Jest results in storybook</div>;
|
||||
defaultView.parameters = {
|
||||
jest: { disable: true },
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-jest",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "React storybook addon that show component jest report",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -35,11 +35,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -23,35 +23,34 @@ within `.storybook/main.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
addons: ['@storybook/addon-knobs']
|
||||
}
|
||||
addons: ['@storybook/addon-knobs'],
|
||||
};
|
||||
```
|
||||
|
||||
Now, write your stories with Knobs.
|
||||
|
||||
### With React
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import { withKnobs, text, boolean, number } from "@storybook/addon-knobs";
|
||||
import React from 'react';
|
||||
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
|
||||
|
||||
export default {
|
||||
title: "Storybook Knobs",
|
||||
decorators: [withKnobs]
|
||||
title: 'Storybook Knobs',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
// Add the `withKnobs` decorator to add knobs support to your stories.
|
||||
// You can also configure `withKnobs` as a global decorator.
|
||||
|
||||
// Knobs for React props
|
||||
export const withAButton = () => (
|
||||
<button disabled={boolean("Disabled", false)}>
|
||||
{text("Label", "Hello Storybook")}
|
||||
</button>
|
||||
<button disabled={boolean('Disabled', false)}>{text('Label', 'Hello Storybook')}</button>
|
||||
);
|
||||
|
||||
// Knobs as dynamic variables.
|
||||
export const asDynamicVariables = () => {
|
||||
const name = text("Name", "James");
|
||||
const age = number("Age", 35);
|
||||
const name = text('Name', 'James');
|
||||
const age = number('Age', 35);
|
||||
const content = `I am ${name} and I'm ${age} years old.`;
|
||||
|
||||
return <div>{content}</div>;
|
||||
@ -59,7 +58,9 @@ export const asDynamicVariables = () => {
|
||||
```
|
||||
|
||||
### With Vue.js
|
||||
|
||||
MyButton.story.js:
|
||||
|
||||
```js
|
||||
import { storiesOf } from '@storybook/vue';
|
||||
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
|
||||
@ -67,8 +68,8 @@ import { withKnobs, text, boolean } from '@storybook/addon-knobs';
|
||||
import MyButton from './MyButton.vue';
|
||||
|
||||
export default {
|
||||
title: "Storybook Knobs",
|
||||
decorators: [withKnobs]
|
||||
title: 'Storybook Knobs',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
|
||||
// Assign `props` to the story's component, calling
|
||||
@ -80,17 +81,18 @@ export const exampleWithKnobs = () => ({
|
||||
components: { MyButton },
|
||||
props: {
|
||||
isDisabled: {
|
||||
default: boolean('Disabled', false)
|
||||
default: boolean('Disabled', false),
|
||||
},
|
||||
text: {
|
||||
default: text('Text', 'Hello Storybook')
|
||||
}
|
||||
default: text('Text', 'Hello Storybook'),
|
||||
},
|
||||
},
|
||||
template: `<MyButton :isDisabled="isDisabled">{{ text }}</MyButton>`
|
||||
template: `<MyButton :isDisabled="isDisabled">{{ text }}</MyButton>`,
|
||||
});
|
||||
```
|
||||
|
||||
MyButton.vue:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<button :disabled="isDisabled">
|
||||
@ -103,14 +105,15 @@ export default {
|
||||
props: {
|
||||
isDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
### With Angular
|
||||
|
||||
```js
|
||||
import { storiesOf } from '@storybook/angular';
|
||||
import { boolean, number, text, withKnobs } from '@storybook/addon-knobs';
|
||||
@ -118,8 +121,8 @@ import { boolean, number, text, withKnobs } from '@storybook/addon-knobs';
|
||||
import { Button } from '@storybook/angular/demo';
|
||||
|
||||
export default {
|
||||
title: "Storybook Knobs",
|
||||
decorators: [withKnobs]
|
||||
title: 'Storybook Knobs',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
|
||||
export const withKnobs = () => ({
|
||||
@ -131,6 +134,7 @@ export const withKnobs = () => ({
|
||||
```
|
||||
|
||||
### With Ember
|
||||
|
||||
```js
|
||||
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
@ -160,9 +164,9 @@ export const inGroups = () => {
|
||||
const personalGroupId = 'personal info';
|
||||
const generalGroupId = 'general info';
|
||||
|
||||
const name = text("Name", "James", personalGroupId);
|
||||
const age = number("Age", 35, {min: 0, max: 99}, personalGroupId);
|
||||
const message = text("Hello!", 35, generalGroupId);
|
||||
const name = text('Name', 'James', personalGroupId);
|
||||
const age = number('Age', 35, { min: 0, max: 99 }, personalGroupId);
|
||||
const message = text('Hello!', 35, generalGroupId);
|
||||
const content = `
|
||||
I am ${name} and I'm ${age} years old.
|
||||
${message}
|
||||
@ -245,10 +249,10 @@ import { number } from '@storybook/addon-knobs';
|
||||
const label = 'Temperature';
|
||||
const defaultValue = 73;
|
||||
const options = {
|
||||
range: true,
|
||||
min: 60,
|
||||
max: 90,
|
||||
step: 1,
|
||||
range: true,
|
||||
min: 60,
|
||||
max: 90,
|
||||
step: 1,
|
||||
};
|
||||
const groupId = 'GROUP-ID1';
|
||||
|
||||
@ -345,7 +349,7 @@ Options can also be an array:
|
||||
```js
|
||||
import { select } from '@storybook/addon-knobs';
|
||||
const label = 'Cats';
|
||||
const options = ['linus', 'eleanor', 'lover']
|
||||
const options = ['linus', 'eleanor', 'lover'];
|
||||
const defaultValue = 'eleanor';
|
||||
const groupId = 'GROUP-ID2';
|
||||
const value = select(label, options, defaultValue, groupId);
|
||||
@ -393,7 +397,7 @@ const value = radios(label, options, defaultValue, groupId);
|
||||
|
||||
### options
|
||||
|
||||
Configurable UI for selecting a value from a set of options.
|
||||
Configurable UI for selecting a value from a set of options.
|
||||
|
||||
```js
|
||||
import { optionsKnob as options } from '@storybook/addon-knobs';
|
||||
@ -406,13 +410,15 @@ const valuesObj = {
|
||||
};
|
||||
const defaultValue = 'kiwi';
|
||||
const optionsObj = {
|
||||
display: 'inline-radio'
|
||||
display: 'inline-radio',
|
||||
};
|
||||
const groupId = 'GROUP-ID1';
|
||||
|
||||
const value = options(label, valuesObj, defaultValue, optionsObj, groupId);
|
||||
```
|
||||
|
||||
> The display property for `optionsObj` accepts:
|
||||
>
|
||||
> - `radio`
|
||||
> - `inline-radio`
|
||||
> - `check`
|
||||
@ -459,8 +465,8 @@ If your component needs the date in a different form you can wrap the `date` fun
|
||||
|
||||
```js
|
||||
function myDateKnob(name, defaultValue) {
|
||||
const stringTimestamp = date(name, defaultValue)
|
||||
return new Date(stringTimestamp)
|
||||
const stringTimestamp = date(name, defaultValue);
|
||||
return new Date(stringTimestamp);
|
||||
}
|
||||
```
|
||||
|
||||
@ -494,20 +500,16 @@ export default {
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
|
||||
export const defaultView = () => (
|
||||
<div />
|
||||
);
|
||||
defaultView.story = {
|
||||
parameters: {
|
||||
knobs: {
|
||||
// Doesn't emit events while user is typing.
|
||||
timestamps: true,
|
||||
export const defaultView = () => <div />;
|
||||
defaultView.parameters = {
|
||||
knobs: {
|
||||
// Doesn't emit events while user is typing.
|
||||
timestamps: true,
|
||||
|
||||
// Escapes strings to be safe for inserting as innerHTML. This option is true by default. It's safe to set it to `false` with frameworks like React which do escaping on their side.
|
||||
// You can still set it to false, but it's strongly discouraged to set to true in cases when you host your storybook on some route of your main site or web app.
|
||||
escapeHTML: true,
|
||||
}
|
||||
}
|
||||
// Escapes strings to be safe for inserting as innerHTML. This option is true by default. It's safe to set it to `false` with frameworks like React which do escaping on their side.
|
||||
// You can still set it to false, but it's strongly discouraged to set to true in cases when you host your storybook on some route of your main site or web app.
|
||||
escapeHTML: true,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -518,9 +520,8 @@ If you are using Typescript, make sure you have the type definitions installed f
|
||||
- node
|
||||
- react
|
||||
|
||||
You can install them using: (*assuming you are using Typescript >2.0.*)
|
||||
You can install them using: (_assuming you are using Typescript >2.0._)
|
||||
|
||||
```sh
|
||||
yarn add @types/node @types/react --dev
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-knobs",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook Addon Prop Editor Component",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -29,13 +29,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/channels": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/channels": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"@types/react-color": "^3.0.1",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-links",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Story Links addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -29,11 +29,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/csf": "0.0.1",
|
||||
"@storybook/router": "6.0.0-beta.12",
|
||||
"@storybook/router": "6.0.0-beta.14",
|
||||
"@types/qs": "^6.9.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-queryparams",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "parameter addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -30,12 +30,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"qs": "^6.6.0",
|
||||
|
@ -33,29 +33,28 @@ Now run your Jest test command. (Usually, `npm test`.) Then you can see all of y
|
||||
|
||||

|
||||
|
||||
|
||||
## Configure your app for Jest
|
||||
|
||||
In many cases, for example Create React App, it's already configured for Jest. You need to create a filename with the extension `.test.js`.
|
||||
|
||||
If you still need to configure jest you can use the resources mentioned below:
|
||||
|
||||
- [Getting Started - Jest Official Documentation](https://facebook.github.io/jest/docs/en/getting-started.html)
|
||||
- [Javascript Testing with Jest - Egghead](https://egghead.io/lessons/javascript-test-javascript-with-jest). ***paid content***
|
||||
- [Getting Started - Jest Official Documentation](https://facebook.github.io/jest/docs/en/getting-started.html)
|
||||
- [Javascript Testing with Jest - Egghead](https://egghead.io/lessons/javascript-test-javascript-with-jest). **_paid content_**
|
||||
|
||||
> Note: If you use React 16, you'll need to follow [these additional instructions](https://github.com/facebook/react/issues/9102#issuecomment-283873039).
|
||||
>
|
||||
> Note: Make sure you have added the ```json``` extension to ```moduleFileExtensions``` in ```jest.config.json```. If this is missing it leads to the [following error](https://github.com/storybookjs/storybook/issues/3728): ```Cannot find module 'spdx-license-ids' from 'scan.js'```.
|
||||
> Note: Make sure you have added the `json` extension to `moduleFileExtensions` in `jest.config.json`. If this is missing it leads to the [following error](https://github.com/storybookjs/storybook/issues/3728): `Cannot find module 'spdx-license-ids' from 'scan.js'`.
|
||||
>
|
||||
> Note: Please make sure you are using ```jsdom``` as the testEnvironment on your jest config file.
|
||||
|
||||
> Note: Please make sure you are using `jsdom` as the testEnvironment on your jest config file.
|
||||
|
||||
### Configure Jest to work with Webpack's [require.context()](https://webpack.js.org/guides/dependency-management/#require-context)
|
||||
|
||||
**NOTE**: if you are using Storybook 5.3's `main.js` to list story files, this is no longer needed.
|
||||
|
||||
Sometimes it's useful to configure Storybook with Webpack's require.context feature. You could be loading stories [one of two ways](https://storybook.js.org/docs/basics/writing-stories/#loading-stories).
|
||||
Sometimes it's useful to configure Storybook with Webpack's require.context feature. You could be loading stories [one of two ways](https://storybook.js.org/docs/basics/writing-stories/#loading-stories).
|
||||
|
||||
1) If you're using the `storiesOf` API, you can integrate it this way:
|
||||
1. If you're using the `storiesOf` API, you can integrate it this way:
|
||||
|
||||
```js
|
||||
import { configure } from '@storybook/react';
|
||||
@ -63,13 +62,13 @@ import { configure } from '@storybook/react';
|
||||
const req = require.context('../stories', true, /\.stories\.js$/); // <- import all the stories at once
|
||||
|
||||
function loadStories() {
|
||||
req.keys().forEach(filename => req(filename));
|
||||
req.keys().forEach((filename) => req(filename));
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
||||
```
|
||||
|
||||
2) If you're using Component Story Format (CSF), you'll integrate it like so:
|
||||
2. If you're using Component Story Format (CSF), you'll integrate it like so:
|
||||
|
||||
```js
|
||||
import { configure } from '@storybook/react';
|
||||
@ -77,7 +76,7 @@ import { configure } from '@storybook/react';
|
||||
const req = require.context('../stories', true, /\.stories\.js$/); // <- import all the stories at once
|
||||
|
||||
configure(req, module);
|
||||
```
|
||||
```
|
||||
|
||||
The problem here is that it will work only during the build with webpack,
|
||||
other tools may lack this feature. Since Storyshot is running under Jest,
|
||||
@ -100,11 +99,13 @@ Next, it needs to be registered and loaded before each test. To register it, cre
|
||||
import registerRequireContextHook from 'babel-plugin-require-context-hook/register';
|
||||
registerRequireContextHook();
|
||||
```
|
||||
|
||||
That file needs to be added as a setup file for Jest. To do that, add (or create) a property in Jest's config called [`setupFiles`](https://jestjs.io/docs/en/configuration.html#setupfiles-array). Add the file name and path to this array.
|
||||
|
||||
```json
|
||||
setupFiles: ['<rootDir>/.jest/register-context.js']
|
||||
```
|
||||
|
||||
Finally, add the plugin to `.babelrc`:
|
||||
|
||||
```json
|
||||
@ -118,6 +119,7 @@ Finally, add the plugin to `.babelrc`:
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The plugin is only added to the test environment otherwise it could replace webpack's version of it.
|
||||
|
||||
#### Option 2: Macro
|
||||
@ -138,6 +140,7 @@ const req = requireContext('../stories', true, /\.stories\.js$/);
|
||||
```
|
||||
|
||||
### Configure Jest for React
|
||||
|
||||
StoryShots addon for React is dependent on [react-test-renderer](https://github.com/facebook/react/tree/master/packages/react-test-renderer), but
|
||||
[doesn't](#deps-issue) install it, so you need to install it separately.
|
||||
|
||||
@ -146,6 +149,7 @@ yarn add react-test-renderer --dev
|
||||
```
|
||||
|
||||
### Configure Jest for Angular
|
||||
|
||||
StoryShots addon for Angular is dependent on [jest-preset-angular](https://github.com/thymikee/jest-preset-angular), but
|
||||
[doesn't](#deps-issue) install it, so you need to install it separately.
|
||||
|
||||
@ -155,6 +159,7 @@ yarn add jest-preset-angular
|
||||
|
||||
If you already use Jest for testing your angular app - probably you already have the needed jest configuration.
|
||||
Anyway you can add these lines to your jest config:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
globals: {
|
||||
@ -167,7 +172,9 @@ module.exports = {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', '.html'],
|
||||
};
|
||||
```
|
||||
|
||||
### Configure Jest for Vue
|
||||
|
||||
StoryShots addon for Vue is dependent on [jest-vue-preprocessor](https://github.com/vire/jest-vue-preprocessor), but
|
||||
[doesn't](#deps-issue) install it, so you need to install it separately.
|
||||
|
||||
@ -177,20 +184,20 @@ yarn add jest-vue-preprocessor
|
||||
|
||||
If you already use Jest for testing your vue app - probably you already have the needed jest configuration.
|
||||
Anyway you can add these lines to your jest config:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
transform: {
|
||||
'^.+\\.jsx?$': 'babel-jest',
|
||||
'.*\\.(vue)$': '<rootDir>/node_modules/jest-vue-preprocessor',
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'/node_modules/(?!(@storybook/.*\\.vue$))',
|
||||
],
|
||||
transformIgnorePatterns: ['/node_modules/(?!(@storybook/.*\\.vue$))'],
|
||||
moduleFileExtensions: ['vue', 'js', 'jsx', 'json', 'node'],
|
||||
};
|
||||
```
|
||||
|
||||
### Configure Jest for Preact
|
||||
|
||||
StoryShots addon for Preact is dependent on [preact-render-to-json](https://github.com/nathancahill/preact-render-to-json), but
|
||||
[doesn't](#deps-issue) install it, so you need to install it separately.
|
||||
|
||||
@ -200,7 +207,7 @@ yarn add preact-render-to-json --dev
|
||||
|
||||
### Configure Jest for MDX Docs Add-On Stories
|
||||
|
||||
If using the [Docs add-on](../../docs/README.md) with
|
||||
If using the [Docs add-on](../../docs/README.md) with
|
||||
[MDX stories](../../docs/docs/mdx.md) you will need
|
||||
to configure Jest to transform MDX stories into something Storyshots can understand:
|
||||
|
||||
@ -216,6 +223,7 @@ Add the following to your Jest configuration:
|
||||
```
|
||||
|
||||
### <a name="deps-issue"></a>Why don't we install dependencies of each framework ?
|
||||
|
||||
Storyshots addon is currently supporting React, Angular and Vue. Each framework needs its own packages to be integrated with Jest. We don't want people that use only React will need to bring other dependencies that do not make sense for them.
|
||||
|
||||
`dependencies` - will installed an exact version of the particular dep - Storyshots can work with different versions of the same framework (let's say React v16 and React v15), that have to be compatible with a version of its plugin (react-test-renderer).
|
||||
@ -238,34 +246,33 @@ out elements that rely on refs, you will have to use the
|
||||
Here is an example of how to specify the `createNodeMock` option in Storyshots:
|
||||
|
||||
```js
|
||||
import initStoryshots, { snapshotWithOptions } from '@storybook/addon-storyshots'
|
||||
import TextareaThatUsesRefs from '../component/TextareaThatUsesRefs'
|
||||
import initStoryshots, { snapshotWithOptions } from '@storybook/addon-storyshots';
|
||||
import TextareaThatUsesRefs from '../component/TextareaThatUsesRefs';
|
||||
|
||||
initStoryshots({
|
||||
test: snapshotWithOptions({
|
||||
createNodeMock: (element) => {
|
||||
if (element.type === TextareaThatUsesRefs) {
|
||||
return document.createElement('textarea')
|
||||
return document.createElement('textarea');
|
||||
}
|
||||
},
|
||||
}),
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
Provide a function to have story-specific options:
|
||||
|
||||
|
||||
```js
|
||||
initStoryshots({
|
||||
test: snapshotWithOptions(story =>({
|
||||
test: snapshotWithOptions((story) => ({
|
||||
createNodeMock: (element) => {
|
||||
if(story.name == 'foobar') {
|
||||
return null
|
||||
if (story.name == 'foobar') {
|
||||
return null;
|
||||
}
|
||||
return element
|
||||
return element;
|
||||
},
|
||||
})),
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
### StoryShots for async rendered components
|
||||
@ -280,28 +287,28 @@ Add _stories of UserForm_ in the file: UserForm.story.jsx
|
||||
|
||||
```jsx
|
||||
/* global module */
|
||||
import React from "react";
|
||||
import { QueryRenderer } from "react-relay";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import React from 'react';
|
||||
import { QueryRenderer } from 'react-relay';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
|
||||
// Use the same queries used in YOUR app routes
|
||||
import { newUserFormQuery, editUserFormQuery } from "app/routes";
|
||||
import UserFormContainer from "app/users/UserForm";
|
||||
import { newUserFormQuery, editUserFormQuery } from 'app/routes';
|
||||
import UserFormContainer from 'app/users/UserForm';
|
||||
|
||||
// YOUR function to generate a Relay Environment mock.
|
||||
// See https://github.com/1stdibs/relay-mock-network-layer for more info
|
||||
import getEnvironment from "test/support/relay-environment-mock";
|
||||
import getEnvironment from 'test/support/relay-environment-mock';
|
||||
|
||||
// User test data YOU generated for your tests
|
||||
import { user } from "test/support/data/index";
|
||||
import { user } from 'test/support/data/index';
|
||||
|
||||
// Use this function to return a new Environment for each story
|
||||
const Environment = () =>
|
||||
getEnvironment({
|
||||
mocks: {
|
||||
Node: () => ({ __typename: "User" }),
|
||||
User: () => user
|
||||
}
|
||||
Node: () => ({ __typename: 'User' }),
|
||||
User: () => user,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
@ -328,23 +335,23 @@ const renderStory = (query, environment, variables = {}) => (
|
||||
/>
|
||||
);
|
||||
|
||||
storiesOf("users/UserForm", module)
|
||||
.add("New User", () => {
|
||||
storiesOf('users/UserForm', module)
|
||||
.add('New User', () => {
|
||||
const environment = new Environment();
|
||||
return renderStory(newUserFormQuery, environment);
|
||||
})
|
||||
.add("Editing User", () => {
|
||||
.add('Editing User', () => {
|
||||
const environment = new Environment();
|
||||
return renderStory(editUserFormQuery, environment, { id: user.id });
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
Then, init Storyshots for async component in the file: StoryShots.test.js
|
||||
|
||||
```jsx
|
||||
import initStoryshots, { Stories2SnapsConverter } from "@storybook/addon-storyshots";
|
||||
import { mount } from "enzyme";
|
||||
import toJson from "enzyme-to-json";
|
||||
import initStoryshots, { Stories2SnapsConverter } from '@storybook/addon-storyshots';
|
||||
import { mount } from 'enzyme';
|
||||
import toJson from 'enzyme-to-json';
|
||||
|
||||
// Runner
|
||||
initStoryshots({
|
||||
@ -352,7 +359,7 @@ initStoryshots({
|
||||
test: ({
|
||||
story,
|
||||
context,
|
||||
done // --> callback passed to test method when asyncJest option is true
|
||||
done, // --> callback passed to test method when asyncJest option is true
|
||||
}) => {
|
||||
const converter = new Stories2SnapsConverter();
|
||||
const snapshotFilename = converter.getSnapshotFileName(context);
|
||||
@ -371,12 +378,12 @@ initStoryshots({
|
||||
}
|
||||
|
||||
done();
|
||||
}, waitTime)
|
||||
}, waitTime);
|
||||
},
|
||||
// other options here
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
NOTICE that When using the `asyncJest: true` option, you also must specify a `test` method that calls the `done()` callback.
|
||||
|
||||
This is a really powerful technique to write stories of Relay components because it integrates data fetching with component rendering. So instead of passing data props manually, we can let Relay do the job for us as it does in our application.
|
||||
@ -405,8 +412,8 @@ initStoryshots({
|
||||
|
||||
By default, Storyshots assumes the config directory path for your project as below:
|
||||
|
||||
- Storybook for React: `.storybook`
|
||||
- Storybook for React Native: `storybook`
|
||||
- Storybook for React: `.storybook`
|
||||
- Storybook for React Native: `storybook`
|
||||
|
||||
If you are using a different config directory path, you could change it like this:
|
||||
|
||||
@ -414,7 +421,7 @@ If you are using a different config directory path, you could change it like thi
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
|
||||
initStoryshots({
|
||||
configPath: '.my-storybook-config-dir'
|
||||
configPath: '.my-storybook-config-dir',
|
||||
});
|
||||
```
|
||||
|
||||
@ -433,15 +440,14 @@ original one. It also may be useful for separating tests to different test confi
|
||||
|
||||
```js
|
||||
initStoryshots({
|
||||
configPath: '.my-storybook-config-dir/testConfig1.js'
|
||||
configPath: '.my-storybook-config-dir/testConfig1.js',
|
||||
});
|
||||
|
||||
initStoryshots({
|
||||
configPath: '.my-storybook-config-dir/testConfig2.js'
|
||||
configPath: '.my-storybook-config-dir/testConfig2.js',
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### `suite`
|
||||
|
||||
By default, Storyshots groups stories inside a Jest test suite called "Storyshots". You could change it like this:
|
||||
@ -450,7 +456,7 @@ By default, Storyshots groups stories inside a Jest test suite called "Storyshot
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
|
||||
initStoryshots({
|
||||
suite: 'MyStoryshots'
|
||||
suite: 'MyStoryshots',
|
||||
});
|
||||
```
|
||||
|
||||
@ -462,7 +468,7 @@ If you'd like to only run a subset of the stories for your snapshot tests based
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
|
||||
initStoryshots({
|
||||
storyKindRegex: /^MyComponent$/
|
||||
storyKindRegex: /^MyComponent$/,
|
||||
});
|
||||
```
|
||||
|
||||
@ -474,7 +480,7 @@ If you want to run all stories except stories of a specific kind, you can write
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
|
||||
initStoryshots({
|
||||
storyKindRegex:/^((?!.*?DontTest).)*$/
|
||||
storyKindRegex: /^((?!.*?DontTest).)*$/,
|
||||
});
|
||||
```
|
||||
|
||||
@ -489,7 +495,7 @@ If you'd like to only run a subset of the stories for your snapshot tests based
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
|
||||
initStoryshots({
|
||||
storyNameRegex: /buttons/
|
||||
storyNameRegex: /buttons/,
|
||||
});
|
||||
```
|
||||
|
||||
@ -533,7 +539,6 @@ initStoryshots({
|
||||
If you are using enzyme, you need to make sure jest knows how to serialize rendered components.
|
||||
For that, you can pass an enzyme-compatible snapshotSerializer (like [enzyme-to-json](https://github.com/adriantoine/enzyme-to-json), [jest-serializer-enzyme](https://github.com/rogeliog/jest-serializer-enzyme) etc.) with the `snapshotSerializer` option (see below).
|
||||
|
||||
|
||||
### `snapshotSerializers`
|
||||
|
||||
Pass an array of snapshotSerializers to the jest runtime that serializes your story (such as enzyme-to-json).
|
||||
@ -549,8 +554,9 @@ initStoryshots({
|
||||
```
|
||||
|
||||
This option needs to be set if either:
|
||||
* the multiSnapshot function is used to create multiple snapshot files (i.e. one per story), since it ignores any serializers specified in your jest config.
|
||||
* serializers not specified in your jest config should be used when snapshotting stories.
|
||||
|
||||
- the multiSnapshot function is used to create multiple snapshot files (i.e. one per story), since it ignores any serializers specified in your jest config.
|
||||
- serializers not specified in your jest config should be used when snapshotting stories.
|
||||
|
||||
### `serializer` (deprecated)
|
||||
|
||||
@ -569,6 +575,7 @@ initStoryshots({
|
||||
This option only needs to be set if the default `snapshotSerializers` is not set in your jest config.
|
||||
|
||||
### `stories2snapsConverter`
|
||||
|
||||
This parameter should be an instance of the [`Stories2SnapsConverter`](src/Stories2SnapsConverter.js) (or a derived from it) Class that is used to convert story-file name to snapshot-file name and vice versa.
|
||||
|
||||
By default, the instance of this class is created with these default options:
|
||||
@ -592,7 +599,6 @@ initStoryshots({
|
||||
storiesExtensions: ['.foo'],
|
||||
}),
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
## Exports
|
||||
@ -620,6 +626,7 @@ Like the default, but allows you to specify a set of options for the renderer, j
|
||||
|
||||
Like `snapshotWithOptions`, but generate a separate snapshot file for each stories file rather than a single monolithic file (as is the convention in Jest). This makes it dramatically easier to review changes. If you'd like the benefit of separate snapshot files, but don't have custom options to pass, you can pass an empty object.
|
||||
If you use [Component Story Format](https://storybook.js.org/docs/formats/component-story-format/), you may also need to add an additional Jest transform to automate detecting story file names:
|
||||
|
||||
```js
|
||||
// jest.config.js
|
||||
module.exports = {
|
||||
@ -670,7 +677,7 @@ initStoryshots({
|
||||
if (snapshotFileName) {
|
||||
expect(toJson(shallowTree)).toMatchSpecificSnapshot(snapshotFileName);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@ -678,7 +685,6 @@ initStoryshots({
|
||||
|
||||
Enables Jest `done()` callback in the StoryShots tests for async testing. See [StoryShots for async rendered components](#storyshots-for-async-rendered-components) for more info.
|
||||
|
||||
|
||||
## Story Parameters
|
||||
|
||||
### `disable`
|
||||
@ -689,10 +695,8 @@ Some stories are difficult or impossible to snapshot, such as those covering com
|
||||
export const Exception = () => {
|
||||
throw new Error('storyFn threw an error! WHOOPS');
|
||||
};
|
||||
Exception.story = {
|
||||
name: 'story throws exception',
|
||||
parameters: {
|
||||
storyshots: { disable: true },
|
||||
},
|
||||
Exception.storyName = 'story throws exception';
|
||||
Exception.parameters = {
|
||||
storyshots: { disable: true },
|
||||
};
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -33,9 +33,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/transform": "^26.0.0",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/jest": "^25.1.1",
|
||||
"@types/jest-specific-snapshot": "^0.5.3",
|
||||
@ -50,8 +50,8 @@
|
||||
"ts-dedent": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-docs": "6.0.0-beta.12",
|
||||
"@storybook/react": "6.0.0-beta.12",
|
||||
"@storybook/addon-docs": "6.0.0-beta.14",
|
||||
"@storybook/react": "6.0.0-beta.14",
|
||||
"babel-loader": "^8.0.6",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-to-json": "^3.4.1",
|
||||
|
@ -31,6 +31,4 @@ export default {
|
||||
};
|
||||
|
||||
export const withTimeout = () => <AsyncTestComponent />;
|
||||
withTimeout.story = {
|
||||
name: `with ${TIMEOUT}ms timeout simulating async operation`,
|
||||
};
|
||||
withTimeout.storyName = `with ${TIMEOUT}ms timeout simulating async operation`;
|
||||
|
@ -21,6 +21,4 @@ export const withSomeEmoji = () => (
|
||||
</Button>
|
||||
);
|
||||
|
||||
withSomeEmoji.story = {
|
||||
name: 'with some emoji',
|
||||
};
|
||||
withSomeEmoji.storyName = 'with some emoji';
|
||||
|
@ -13,6 +13,4 @@ export default {
|
||||
|
||||
export const toStorybook = () => <Welcome showApp={linkTo('Button')} />;
|
||||
|
||||
toStorybook.story = {
|
||||
name: 'to Storybook',
|
||||
};
|
||||
toStorybook.storyName = 'to Storybook';
|
||||
|
@ -22,6 +22,7 @@ When willing to run Puppeteer tests for your stories, you have two options:
|
||||
Then you will need to reference the storybook URL (`file://...` if local, `http(s)://...` if served)
|
||||
|
||||
## _puppeteerTest_
|
||||
|
||||
Allows to define arbitrary Puppeteer tests as `story.parameters.puppeteerTest` function.
|
||||
|
||||
You can either create a new Storyshots instance or edit the one you previously used:
|
||||
@ -34,17 +35,16 @@ initStoryshots({ suite: 'Puppeteer storyshots', test: puppeteerTest() });
|
||||
```
|
||||
|
||||
Then, in your stories:
|
||||
|
||||
```js
|
||||
export const myExample = () => {
|
||||
...
|
||||
};
|
||||
myExample.story = {
|
||||
parameters: {
|
||||
async puppeteerTest(page) {
|
||||
const element = await page.$('<some-selector>');
|
||||
await element.click();
|
||||
expect(something).toBe(something);
|
||||
},
|
||||
myExample.parameters = {
|
||||
async puppeteerTest(page) {
|
||||
const element = await page.$('<some-selector>');
|
||||
await element.click();
|
||||
expect(something).toBe(something);
|
||||
},
|
||||
};
|
||||
```
|
||||
@ -80,7 +80,7 @@ import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
|
||||
|
||||
initStoryshots({
|
||||
suite: 'Puppeteer storyshots',
|
||||
test: puppeteerTest({
|
||||
test: puppeteerTest({
|
||||
storybookUrl: 'file:///path/to/my/storybook-static',
|
||||
// storybookUrl: 'file://${path.resolve(__dirname, '../storybook-static')}'
|
||||
}),
|
||||
@ -132,7 +132,7 @@ import initStoryshots from '@storybook/addon-storyshots';
|
||||
import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
|
||||
import puppeteer from 'puppeteer';
|
||||
|
||||
(async function() {
|
||||
(async function () {
|
||||
initStoryshots({
|
||||
suite: 'Puppeteer storyshots',
|
||||
test: puppeteerTest({
|
||||
@ -216,6 +216,7 @@ This can be achieved by adding a step before running the test ie: `npm run build
|
||||
If you run the Puppeteer storyshots against a running Storybook in dev mode, you don't have to worry about the stories being up-to-date because the dev-server is watching changes and rebuilds automatically.
|
||||
|
||||
## _axeTest_
|
||||
|
||||
Runs [Axe](https://www.deque.com/axe/) accessibility checks and verifies that they pass using [jest-puppeteer-axe](https://github.com/WordPress/gutenberg/tree/master/packages/jest-puppeteer-axe).
|
||||
|
||||
```js
|
||||
@ -228,6 +229,7 @@ initStoryshots({ suite: 'A11y checks', test: axeTest() });
|
||||
For configuration, it uses the same `story.parameters.a11y` parameter as [`@storybook/addon-a11y`](https://github.com/storybookjs/storybook/tree/next/addons/a11y#parameters)
|
||||
|
||||
## _imageSnapshots_
|
||||
|
||||
Generates and compares screenshots of your stories using [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot).
|
||||
|
||||
```js
|
||||
@ -253,14 +255,14 @@ const getMatchOptions = ({ context: { kind, story }, url }) => {
|
||||
};
|
||||
};
|
||||
const beforeScreenshot = (page, { context: { kind, story }, url }) => {
|
||||
return new Promise(resolve =>
|
||||
return new Promise((resolve) =>
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 600)
|
||||
);
|
||||
};
|
||||
const afterScreenshot = ({ image, context }) => {
|
||||
return new Promise(resolve =>
|
||||
return new Promise((resolve) =>
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 600)
|
||||
@ -268,7 +270,12 @@ const afterScreenshot = ({ image, context }) => {
|
||||
};
|
||||
initStoryshots({
|
||||
suite: 'Image storyshots',
|
||||
test: imageSnapshot({ storybookUrl: 'http://localhost:6006', getMatchOptions, beforeScreenshot, afterScreenshot }),
|
||||
test: imageSnapshot({
|
||||
storybookUrl: 'http://localhost:6006',
|
||||
getMatchOptions,
|
||||
beforeScreenshot,
|
||||
afterScreenshot,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots-puppeteer",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Image snapshots addition to StoryShots based on puppeteer",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -30,7 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/csf": "0.0.1",
|
||||
"@storybook/node-logger": "6.0.0-beta.12",
|
||||
"@storybook/node-logger": "6.0.0-beta.14",
|
||||
"@types/jest-image-snapshot": "^2.8.0",
|
||||
"@wordpress/jest-puppeteer-axe": "^1.5.0",
|
||||
"core-js": "^3.0.1",
|
||||
@ -42,7 +42,7 @@
|
||||
"@types/puppeteer": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/addon-storyshots": "6.0.0-beta.12",
|
||||
"@storybook/addon-storyshots": "6.0.0-beta.14",
|
||||
"puppeteer": "^2.0.0 || ^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storysource",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Stories addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -29,20 +29,20 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/router": "6.0.0-beta.12",
|
||||
"@storybook/source-loader": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/router": "6.0.0-beta.14",
|
||||
"@storybook/source-loader": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"estraverse": "^4.2.0",
|
||||
"loader-utils": "^2.0.0",
|
||||
"prettier": "^2.0.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.9.17",
|
||||
"react-syntax-highlighter": "^11.0.2",
|
||||
"react-syntax-highlighter": "^12.2.1",
|
||||
"regenerator-runtime": "^0.13.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-toolbars",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook toolbars addon",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -30,10 +30,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -103,19 +103,17 @@ Parameters can be configured for a whole set of stories or a single story via th
|
||||
export default {
|
||||
title: 'Stories',
|
||||
parameters: {
|
||||
viewport: {
|
||||
viewport: {
|
||||
viewports: INITIAL_VIEWPORTS,
|
||||
defaultViewport: 'iphone6'
|
||||
defaultViewport: 'iphone6'
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const myStory = () => <div />;
|
||||
myStory.story = {
|
||||
parameters: {
|
||||
viewport: {
|
||||
defaultViewport: 'iphonex'
|
||||
},
|
||||
myStory.parameters = {
|
||||
viewport: {
|
||||
defaultViewport: 'iphonex'
|
||||
},
|
||||
};
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-viewport",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook addon to change the viewport size to mobile",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -29,12 +29,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"memoizerific": "^1.11.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/angular",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Angular: Develop Angular Components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,9 +34,9 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/node-logger": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@storybook/node-logger": "6.0.0-beta.14",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"autoprefixer": "^9.7.6",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -47,14 +47,19 @@ function getTsConfigOptions(tsConfigPath: Path) {
|
||||
}
|
||||
|
||||
export function getAngularCliConfig(dirToSearch: string) {
|
||||
const fname = path.join(dirToSearch, 'angular.json');
|
||||
const possibleConfigNames = ['angular.json', 'workspace.json'];
|
||||
const possibleConfigPaths = possibleConfigNames
|
||||
.map((name) => path.join(dirToSearch, name))
|
||||
|
||||
if (!fs.existsSync(fname)) {
|
||||
logger.error(`Could not find angular.json using ${fname}`);
|
||||
const validIndex = possibleConfigPaths
|
||||
.findIndex((configPath) => fs.existsSync(configPath));
|
||||
|
||||
if (validIndex === -1) {
|
||||
logger.error(`Could not find angular.json using ${possibleConfigPaths[0]}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return JSON.parse(stripJsonComments(fs.readFileSync(fname, 'utf8')));
|
||||
return JSON.parse(stripJsonComments(fs.readFileSync(possibleConfigPaths[validIndex], 'utf8')));
|
||||
}
|
||||
|
||||
export function getLeadingAngularCliProject(ngCliConfig: any) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/aurelia",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Aurelia: Develop Aurelia Components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -26,10 +26,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addon-knobs": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/node-logger": "6.0.0-beta.12",
|
||||
"@storybook/addon-knobs": "6.0.0-beta.14",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@storybook/node-logger": "6.0.0-beta.14",
|
||||
"fork-ts-checker-webpack-plugin": "^4.0.3",
|
||||
"global": "^4.3.2",
|
||||
"ts-loader": "^6.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/ember",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.",
|
||||
"homepage": "https://github.com/storybookjs/storybook/tree/master/app/ember",
|
||||
"bugs": {
|
||||
@ -32,7 +32,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ember/test-helpers": "^1.7.0",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/html",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,8 +34,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/marionette",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Marionette: Develop Marionette.js component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -25,7 +25,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/marko",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Marko: Develop Marko Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,8 +34,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@marko/webpack": "^2.1.0",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/mithril",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Mithril: Develop Mithril Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -36,8 +36,8 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.9.6",
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@types/mithril": "^2.0.0",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/preact",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Preact: Develop Preact Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -35,8 +35,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/rax",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Rax: Develop Rax Component in isolation.",
|
||||
"keywords": [
|
||||
"rax",
|
||||
@ -34,7 +34,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"babel-preset-rax": "^1.0.0-beta.0",
|
||||
"core-js": "^3.0.1",
|
||||
"driver-dom": "^2.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/react",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -37,9 +37,9 @@
|
||||
"@babel/plugin-transform-react-constant-elements": "^7.6.3",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/node-logger": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@storybook/node-logger": "6.0.0-beta.14",
|
||||
"@svgr/webpack": "^5.4.0",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"babel-plugin-add-react-displayname": "^0.0.5",
|
||||
@ -57,7 +57,7 @@
|
||||
"webpack": "^4.43.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@types/node": "^13.13.4",
|
||||
"@types/webpack": "^4.41.12"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/riot",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for riot.js: View riot snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,7 +34,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"raw-loader": "^4.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/server",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,8 +34,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@storybook/node-logger": "^5.2.8",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/svelte",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,8 +34,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/vue",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for Vue: Develop Vue Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,8 +34,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
@ -47,7 +47,6 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^13.13.4",
|
||||
"@types/webpack": "^4.41.12",
|
||||
"babel-preset-vue": "^2.0.2",
|
||||
"vue": "^2.6.8",
|
||||
"vue-loader": "^15.7.0",
|
||||
"vue-template-compiler": "^2.6.8"
|
||||
|
@ -38,10 +38,3 @@ export function webpack(config: Configuration) {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function babelDefault(config: any) {
|
||||
return {
|
||||
...config,
|
||||
presets: [...config.presets, require.resolve('babel-preset-vue')],
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/web-components",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"lit-html",
|
||||
@ -38,8 +38,8 @@
|
||||
"dependencies": {
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||
"@babel/plugin-syntax-import-meta": "^7.2.0",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/core": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/core": "6.0.0-beta.14",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"babel-plugin-bundled-import-meta": "^0.3.1",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-decorator",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "decorator addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,8 +24,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.4.0"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-parameter",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "parameter addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,12 +24,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-preview-wrapper",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "preview wrapper addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,7 +24,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"react": "^16.8.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-roundtrip",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"description": "roundtrip addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,13 +24,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/api": "6.0.0-beta.12",
|
||||
"@storybook/client-api": "6.0.0-beta.12",
|
||||
"@storybook/client-logger": "6.0.0-beta.12",
|
||||
"@storybook/components": "6.0.0-beta.12",
|
||||
"@storybook/core-events": "6.0.0-beta.12",
|
||||
"@storybook/theming": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/api": "6.0.0-beta.14",
|
||||
"@storybook/client-api": "6.0.0-beta.14",
|
||||
"@storybook/client-logger": "6.0.0-beta.14",
|
||||
"@storybook/components": "6.0.0-beta.14",
|
||||
"@storybook/core-events": "6.0.0-beta.14",
|
||||
"@storybook/theming": "6.0.0-beta.14",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -21,10 +21,7 @@ within `.storybook/main.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
addons: [
|
||||
'@storybook/addon-actions',
|
||||
'@storybook/addon-knobs',
|
||||
],
|
||||
addons: ['@storybook/addon-actions', '@storybook/addon-knobs'],
|
||||
};
|
||||
```
|
||||
|
||||
@ -58,10 +55,8 @@ export const buttonWithEmoji = () => (
|
||||
</span>
|
||||
</Button>
|
||||
);
|
||||
buttonWithEmoji.story = {
|
||||
parameters: {
|
||||
notes: 'A small component',
|
||||
},
|
||||
buttonWithEmoji.parameters = {
|
||||
notes: 'A small component',
|
||||
};
|
||||
```
|
||||
|
||||
@ -89,10 +84,8 @@ export const buttonWithEmoji = () => (
|
||||
</span>
|
||||
</Button>
|
||||
);
|
||||
buttonWithEmoji.story = {
|
||||
parameters: {
|
||||
notes: { disabled: true }
|
||||
}
|
||||
buttonWithEmoji.parameters = {
|
||||
notes: { disabled: true },
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -74,11 +74,11 @@ const PANEL_ID = `${ADDON_ID}/panel`;
|
||||
|
||||
const MyPanel = () => {
|
||||
const value = useParameter(PARAM_KEY, null);
|
||||
const item = value ? value.data : "";
|
||||
const item = value ? value.data : '';
|
||||
return <div>{item}</div>;
|
||||
}
|
||||
};
|
||||
|
||||
addons.register(ADDON_ID, api => {
|
||||
addons.register(ADDON_ID, (api) => {
|
||||
const render = ({ active, key }) => (
|
||||
<AddonPanel active={active} key={key}>
|
||||
<MyPanel />
|
||||
@ -95,20 +95,47 @@ addons.register(ADDON_ID, api => {
|
||||
});
|
||||
```
|
||||
|
||||
### register the addon
|
||||
#### Register the addon
|
||||
|
||||
within `.storybook/main.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
addons: ['path/to/addon']
|
||||
}
|
||||
addons: ['path/to/addon'],
|
||||
};
|
||||
```
|
||||
|
||||
Now restart/rebuild storybook and the addon should show up!
|
||||
Now restart/rebuild storybook and the addon should show up!
|
||||
When changing stories, the addon's onStoryChange method will be invoked with the new storyId.
|
||||
|
||||
#### Note:
|
||||
#### TSX Addons
|
||||
|
||||
When your addon needs additional typing or you want to keep it locally, you can register it within `.storybook/manager.tsx`
|
||||
and import there your TSX components to be compiled by webpack, not requiring an external package nor an additional build step.
|
||||
|
||||
```tsx
|
||||
// manager.tsx
|
||||
|
||||
import React from 'react';
|
||||
import { addons } from '@storybook/addons';
|
||||
import { AddonPanel } from '@storybook/components';
|
||||
import { ADDON_ID, PARAM_KEY, PANEL_ID, MyPanel } from './MyAddon';
|
||||
|
||||
addons.register(ADDON_ID, (api) => {
|
||||
addons.addPanel(PANEL_ID, {
|
||||
title: 'My Addon',
|
||||
paramKey: PARAM_KEY,
|
||||
render: ({ active, key }) => (
|
||||
<AddonPanel active={active} key={key}>
|
||||
<MyPanel />
|
||||
</AddonPanel>
|
||||
),
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Note
|
||||
|
||||
If you get an error similar to:
|
||||
|
||||
```
|
||||
@ -128,7 +155,8 @@ It is likely because you do not have a `.babelrc` file or do not have it configu
|
||||
If we want to create a more complex addon, one that wraps the component being rendered for example, there are a few more steps.
|
||||
Essentially you can start communicating from and to the manager using the storybook API.
|
||||
|
||||
Now we need to create two files, `register.js` and `index.js,`. `register.js` will be loaded by the manager (the outer frame) and `index.js` will be loaded in the iframe/preview. If you want your addon to be framework agnostic, THIS is the file where you need to be careful about that.
|
||||
Now we need to create two files, `register.js` and `index.js,`.
|
||||
`register.js` will be loaded by the manager (the outer frame) and `index.js` will be loaded in the iframe/preview. If you want your addon to be framework agnostic, THIS is the file where you need to be careful about that.
|
||||
|
||||
## Creating a decorator
|
||||
|
||||
@ -154,8 +182,8 @@ export default makeDecorator({
|
||||
// we can also add subscriptions here using channel.on('eventName', callback);
|
||||
|
||||
return getStory(context);
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
In this case, our component can access something called the channel. It lets us communicate with the panel (in the manager).
|
||||
@ -178,15 +206,19 @@ import { AddonPanel } from '@storybook/components';
|
||||
|
||||
const MyPanel = () => {
|
||||
const emit = useChannel({
|
||||
STORY_RENDERED: id => { /* do something */ },
|
||||
'my/customEvent': () => { /* so something */ },
|
||||
STORY_RENDERED: (id) => {
|
||||
/* do something */
|
||||
},
|
||||
'my/customEvent': () => {
|
||||
/* so something */
|
||||
},
|
||||
});
|
||||
|
||||
return <button onClick={() => emit('my/otherEvent')}>click to emit</button>;
|
||||
}
|
||||
};
|
||||
|
||||
// Register the addon with a unique name.
|
||||
addons.register('my/addon', api => {
|
||||
addons.register('my/addon', (api) => {
|
||||
// Also need to set a unique name to the panel.
|
||||
addons.addPanel('my/addon/panel', {
|
||||
title: 'My Addon',
|
||||
@ -217,12 +249,8 @@ A great way of preserving state even when your component is unmounted is using t
|
||||
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>;
|
||||
};
|
||||
```
|
||||
|
||||
This will store your addon's state into storybook core state, and so when your component gets unmounted & remounted, the state will be restored.
|
||||
@ -235,8 +263,8 @@ within `.storybook/main.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
addons: ['path/to/addon']
|
||||
}
|
||||
addons: ['path/to/addon'],
|
||||
};
|
||||
```
|
||||
|
||||
Then you need to start using the decorator:
|
||||
@ -253,21 +281,18 @@ export default {
|
||||
decorators: [withMyAddon],
|
||||
};
|
||||
|
||||
export const defaultView = () => (
|
||||
<Button>Hello Button</Button>
|
||||
);
|
||||
defaultView.story = {
|
||||
parameters: {
|
||||
myParameter: { data: 'awesome' },
|
||||
},
|
||||
export const defaultView = () => <Button>Hello Button</Button>;
|
||||
defaultView.parameters = {
|
||||
myParameter: { data: 'awesome' },
|
||||
};
|
||||
```
|
||||
|
||||
### Disabling an addon panel
|
||||
|
||||
It's possible to disable an addon panel for a particular story.
|
||||
|
||||
|
||||
To offer that capability, you need to pass the paramKey when you register the panel
|
||||
|
||||
```js
|
||||
addons.register(ADDON_ID, () => {
|
||||
addons.add(PANEL_ID, {
|
||||
@ -293,7 +318,6 @@ export default {
|
||||
myAddon: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Styling your addon
|
||||
|
@ -159,7 +159,7 @@ import { configure } from '@storybook/react';
|
||||
const loaderFn = () => {
|
||||
const allExports = [require('./welcome.stories.js')];
|
||||
const req = require.context('../src/components', true, /\.stories\.js$/);
|
||||
req.keys().forEach(fname => allExports.push(req(fname)));
|
||||
req.keys().forEach((fname) => allExports.push(req(fname)));
|
||||
return allExports;
|
||||
};
|
||||
|
||||
@ -180,7 +180,7 @@ const loaderFn = () => {
|
||||
|
||||
// dynamic loading, unavailable in react-native
|
||||
const req = require.context('../src/components', true, /\.stories\.js$/);
|
||||
req.keys().forEach(fname => req(fname));
|
||||
req.keys().forEach((fname) => req(fname));
|
||||
};
|
||||
|
||||
configure(loaderFn, module);
|
||||
@ -200,17 +200,25 @@ Here is an example of a global decorator which centers every story in the `.stor
|
||||
import React from 'react';
|
||||
import { addDecorator } from '@storybook/react';
|
||||
|
||||
addDecorator(storyFn => <div style={{ textAlign: 'center' }}>{storyFn()}</div>);
|
||||
addDecorator((storyFn) => <div style={{ textAlign: 'center' }}>{storyFn()}</div>);
|
||||
```
|
||||
|
||||
> \* In Vue projects you have to use the special component `<story/>` instead of the function parameter `storyFn` that is used in React projects, even if you are using JSX, for example:
|
||||
>
|
||||
> ```jsx
|
||||
> var decoratorVueJsx = () => ({ render() { return <div style={{ textAlign: 'center' }}><story/></div>} })
|
||||
> addDecorator(decoratorVueJsx)
|
||||
> var decoratorVueJsx = () => ({
|
||||
> render() {
|
||||
> return (
|
||||
> <div style={{ textAlign: 'center' }}>
|
||||
> <story />
|
||||
> </div>
|
||||
> );
|
||||
> },
|
||||
> });
|
||||
> addDecorator(decoratorVueJsx);
|
||||
>
|
||||
> var decoratorVueTemplate = () => ({ template: `<div style="text-align:center"><story/></div>` })
|
||||
> addDecorator(decoratorVueTemplate)
|
||||
> var decoratorVueTemplate = () => ({ template: `<div style="text-align:center"><story/></div>` });
|
||||
> addDecorator(decoratorVueTemplate);
|
||||
> ```
|
||||
|
||||
And here's an example of component/local decorators. The component decorator wraps all the stories in a yellow frame, and the story decorator wraps a single story in an additional red frame.
|
||||
@ -221,14 +229,12 @@ import MyComponent from './MyComponent';
|
||||
|
||||
export default {
|
||||
title: 'MyComponent',
|
||||
decorators: [storyFn => <div style={{ backgroundColor: 'yellow' }}>{storyFn()}</div>],
|
||||
decorators: [(storyFn) => <div style={{ backgroundColor: 'yellow' }}>{storyFn()}</div>],
|
||||
};
|
||||
|
||||
export const normal = () => <MyComponent />;
|
||||
export const special = () => <MyComponent text="The Boss" />;
|
||||
special.story = {
|
||||
decorators: [storyFn => <div style={{ border: '5px solid red' }}>{storyFn()}</div>],
|
||||
};
|
||||
special.decorators = [(storyFn) => <div style={{ border: '5px solid red' }}>{storyFn()}</div>];
|
||||
```
|
||||
|
||||
Decorators are not only for story formatting, they are generally useful for any kind of context needed by a story.
|
||||
@ -270,8 +276,8 @@ export default {
|
||||
export const small = () => <MyComponent text="small" />;
|
||||
export const medium = () => <MyComponent text="medium" />;
|
||||
export const special = () => <MyComponent text="The Boss" />;
|
||||
special.story = {
|
||||
parameters: { notes: specialNotes },
|
||||
special.parameters = {
|
||||
notes: specialNotes,
|
||||
};
|
||||
```
|
||||
|
||||
@ -283,8 +289,8 @@ By default, search results will show up based on the file name of your stories.
|
||||
|
||||
```jsx
|
||||
export const callout = () => <Callout>Some children</Callout>;
|
||||
callout.story = {
|
||||
parameters: { notes: 'popover tooltip' },
|
||||
callout.parameters = {
|
||||
notes: 'popover tooltip',
|
||||
};
|
||||
```
|
||||
|
||||
@ -378,9 +384,7 @@ export default {
|
||||
};
|
||||
|
||||
export const Baz = () => <MyComponent />;
|
||||
Baz.story = {
|
||||
name: 'Moo',
|
||||
};
|
||||
Baz.storyName = 'Moo';
|
||||
```
|
||||
|
||||
Storybook will prioritize the `id` over the title for ID generation, if provided, and will prioritize the `story.name` over the export key for display.
|
||||
|
@ -52,18 +52,16 @@ someName1_2_3_4 -> 'Some Name 1 2 3 4'
|
||||
|
||||
It's recommended to start export names with a capital letter.
|
||||
|
||||
Story functions can be annotated with a `story` object to define story-level [decorators](../../basics/writing-stories/#decorators) and [parameters](../../basics/writing-stories/#parameters), and also to define the `name` of the story.
|
||||
Story functions can be annotated with a few different fields to define story-level [decorators](../../basics/writing-stories/#decorators) and [parameters](../../basics/writing-stories/#parameters), and also to define the `storyName` of the story.
|
||||
|
||||
The `name` is useful if you want to use names with special characters, names that correspond to restricted keywords in Javascript, or names that collide with other variables in the file. If it's not specified, the export name will be used instead.
|
||||
The `storyName` is useful if you want to use names with special characters, names that correspond to restricted keywords in Javascript, or names that collide with other variables in the file. If it's not specified, the export name will be used instead.
|
||||
|
||||
```jsx
|
||||
export const Simple = () => <MyComponent />;
|
||||
|
||||
Simple.story = {
|
||||
name: 'So simple!',
|
||||
decorators: [ ... ],
|
||||
parameters: { ... }
|
||||
};
|
||||
Simple.storyName = 'So simple!';
|
||||
Simple.decorators = [ ... ];
|
||||
Simple.parameters = { ... };
|
||||
```
|
||||
|
||||
## Args story inputs
|
||||
@ -84,11 +82,9 @@ Now consider the same example, re-written with args:
|
||||
|
||||
```js
|
||||
export const Text = ({ label, onClick }) => <Button label={label} onClick={onClick} />;
|
||||
Text.story = {
|
||||
args: {
|
||||
label: 'Hello',
|
||||
onClick: action('clicked'),
|
||||
},
|
||||
Text.args = {
|
||||
label: 'Hello',
|
||||
onClick: action('clicked'),
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -71,7 +71,7 @@ And finally, story-level decorators are provided via parameters:
|
||||
storiesOf('Button', module).add(
|
||||
'with text',
|
||||
() => <Button onClick={action('clicked')}>Hello Button</Button>,
|
||||
{ decorators: withKnobs }
|
||||
{ decorators: [withKnobs] }
|
||||
);
|
||||
```
|
||||
|
||||
|
@ -53,11 +53,11 @@ npm install @storybook/vue --save-dev
|
||||
|
||||
### Add peer dependencies
|
||||
|
||||
Make sure that you have `vue`, `vue-loader`, `vue-template-compiler`, `@babel/core`, `babel-loader` and `babel-preset-vue` in your dependencies as well, because we list these as a peer dependencies:
|
||||
Make sure that you have `vue`, `vue-loader`, `vue-template-compiler`, `@babel/core`, and `babel-loader` in your dependencies as well, because we list these as a peer dependencies:
|
||||
|
||||
```sh
|
||||
npm install vue --save
|
||||
npm install vue-loader vue-template-compiler @babel/core babel-loader babel-preset-vue --save-dev
|
||||
npm install vue-loader vue-template-compiler @babel/core babel-loader --save-dev
|
||||
```
|
||||
|
||||
## Step 2: Add npm scripts
|
||||
|
@ -42,13 +42,13 @@ The babel functions `babel`, `babelDefault`, and `managerBabel` all configure ba
|
||||
|
||||
All functions take a [Babel configuration object](https://babeljs.io/docs/en/configuration) as their argument and can modify it or return a new object.
|
||||
|
||||
For example, Storybook's Vue support uses presets internally and here's how it configures babel:
|
||||
For example, Storybook's Mihtril support uses plugins internally and here's how it configures babel:
|
||||
|
||||
```js
|
||||
export function babelDefault(config) {
|
||||
export function babelDefault(config: TransformOptions) {
|
||||
return {
|
||||
...config,
|
||||
presets: [...config.presets, require.resolve('babel-preset-vue')],
|
||||
plugins: [...config.plugins, require.resolve('@babel/plugin-transform-react-jsx')],
|
||||
};
|
||||
}
|
||||
```
|
||||
|
@ -1 +1 @@
|
||||
{"version":"6.0.0-beta.12","info":{"plain":"### Breaking Changes\n\n- Core: Zero-config TypeScript loading ([#10813](https://github.com/storybookjs/storybook/pull/10813))"}}
|
||||
{"version":"6.0.0-beta.14","info":{"plain":"### Breaking Changes\n\n- CSF: Hoist story annotation object ([#10907](https://github.com/storybookjs/storybook/pull/10907))\n- Vue: Remove babel-preset-vue ([#10909](https://github.com/storybookjs/storybook/pull/10909))\n\n### Features\n\n- Angular: Support `workspace.json` in nx workspace ([#10881](https://github.com/storybookjs/storybook/pull/10881))\n\n### Bug Fixes\n\n- Addon-docs: Fix single item width in Preview block ([#10877](https://github.com/storybookjs/storybook/pull/10877))\n- UI: Center toolbar icon buttons ([#10897](https://github.com/storybookjs/storybook/pull/10897))\n- Core: Fix double rendering on startup ([#10892](https://github.com/storybookjs/storybook/pull/10892))\n\n### Maintenance\n\n- Core: Use dedicated loader for es6 modules ([#10783](https://github.com/storybookjs/storybook/pull/10783))\n- Core: Fix yarn test command on windows ([#10904](https://github.com/storybookjs/storybook/pull/10904))"}}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-cli",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.0.0-beta.14",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@ -37,18 +37,18 @@
|
||||
"@angular/cli": "^9.1.0",
|
||||
"@angular/compiler-cli": "^9.1.0",
|
||||
"@compodoc/compodoc": "^1.1.11",
|
||||
"@storybook/addon-a11y": "6.0.0-beta.12",
|
||||
"@storybook/addon-actions": "6.0.0-beta.12",
|
||||
"@storybook/addon-backgrounds": "6.0.0-beta.12",
|
||||
"@storybook/addon-docs": "6.0.0-beta.12",
|
||||
"@storybook/addon-jest": "6.0.0-beta.12",
|
||||
"@storybook/addon-knobs": "6.0.0-beta.12",
|
||||
"@storybook/addon-links": "6.0.0-beta.12",
|
||||
"@storybook/addon-storyshots": "6.0.0-beta.12",
|
||||
"@storybook/addon-storysource": "6.0.0-beta.12",
|
||||
"@storybook/addons": "6.0.0-beta.12",
|
||||
"@storybook/angular": "6.0.0-beta.12",
|
||||
"@storybook/source-loader": "6.0.0-beta.12",
|
||||
"@storybook/addon-a11y": "6.0.0-beta.14",
|
||||
"@storybook/addon-actions": "6.0.0-beta.14",
|
||||
"@storybook/addon-backgrounds": "6.0.0-beta.14",
|
||||
"@storybook/addon-docs": "6.0.0-beta.14",
|
||||
"@storybook/addon-jest": "6.0.0-beta.14",
|
||||
"@storybook/addon-knobs": "6.0.0-beta.14",
|
||||
"@storybook/addon-links": "6.0.0-beta.14",
|
||||
"@storybook/addon-storyshots": "6.0.0-beta.14",
|
||||
"@storybook/addon-storysource": "6.0.0-beta.14",
|
||||
"@storybook/addons": "6.0.0-beta.14",
|
||||
"@storybook/angular": "6.0.0-beta.14",
|
||||
"@storybook/source-loader": "6.0.0-beta.14",
|
||||
"@types/core-js": "^2.5.0",
|
||||
"@types/jest": "^25.1.1",
|
||||
"@types/node": "^13.13.4",
|
||||
|
@ -13,9 +13,7 @@ export const ActionOnly = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
ActionOnly.story = {
|
||||
name: 'Action only',
|
||||
};
|
||||
ActionOnly.storyName = 'Action only';
|
||||
|
||||
export const ActionAndMethod = () => ({
|
||||
component: Button,
|
||||
@ -29,6 +27,4 @@ export const ActionAndMethod = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
ActionAndMethod.story = {
|
||||
name: 'Action and method',
|
||||
};
|
||||
ActionAndMethod.storyName = 'Action and method';
|
||||
|
@ -18,10 +18,8 @@ export const AppComponentWithJestTests = () => ({
|
||||
props: {},
|
||||
});
|
||||
|
||||
AppComponentWithJestTests.story = {
|
||||
name: 'app.component with jest tests',
|
||||
AppComponentWithJestTests.storyName = 'app.component with jest tests';
|
||||
|
||||
parameters: {
|
||||
jest: 'app.component',
|
||||
},
|
||||
AppComponentWithJestTests.parameters = {
|
||||
jest: 'app.component',
|
||||
};
|
||||
|
@ -53,9 +53,7 @@ export const Simple = () => {
|
||||
};
|
||||
};
|
||||
|
||||
Simple.story = {
|
||||
name: 'Simple',
|
||||
};
|
||||
Simple.storyName = 'Simple';
|
||||
|
||||
export const AllKnobs = () => {
|
||||
const name = text('name', 'Jane');
|
||||
@ -101,14 +99,10 @@ export const AllKnobs = () => {
|
||||
};
|
||||
};
|
||||
|
||||
AllKnobs.story = {
|
||||
name: 'All knobs',
|
||||
};
|
||||
AllKnobs.storyName = 'All knobs';
|
||||
|
||||
export const XssSafety = () => ({
|
||||
template: text('Rendered string', '<img src=x onerror="alert(\'XSS Attack\')" >'),
|
||||
});
|
||||
|
||||
XssSafety.story = {
|
||||
name: 'XSS safety',
|
||||
};
|
||||
XssSafety.storyName = 'XSS safety';
|
||||
|
@ -13,6 +13,4 @@ export const ButtonWithLinkToAnotherStory = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
ButtonWithLinkToAnotherStory.story = {
|
||||
name: 'button with link to another story',
|
||||
};
|
||||
ButtonWithLinkToAnotherStory.storyName = 'button with link to another story';
|
||||
|
@ -3,6 +3,9 @@ import { AppComponent } from '../app/app.component';
|
||||
export default {
|
||||
title: 'App Component',
|
||||
component: AppComponent,
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
},
|
||||
};
|
||||
|
||||
export const ComponentWithSeparateTemplate = () => ({
|
||||
@ -10,7 +13,5 @@ export const ComponentWithSeparateTemplate = () => ({
|
||||
props: {},
|
||||
});
|
||||
|
||||
ComponentWithSeparateTemplate.story = {
|
||||
name: 'Component with separate template',
|
||||
parameters: { docs: { iframeHeight: 400 } },
|
||||
};
|
||||
ComponentWithSeparateTemplate.storyName = 'Component with separate template';
|
||||
ComponentWithSeparateTemplate.parameters = { docs: { iframeHeight: 400 } };
|
||||
|
@ -12,9 +12,7 @@ export const InputsAndInjectDependencies = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
InputsAndInjectDependencies.story = {
|
||||
name: 'inputs and inject dependencies',
|
||||
};
|
||||
InputsAndInjectDependencies.storyName = 'inputs and inject dependencies';
|
||||
|
||||
export const InputsAndInjectDependenciesWithKnobs = () => ({
|
||||
component: DiComponent,
|
||||
@ -23,7 +21,5 @@ export const InputsAndInjectDependenciesWithKnobs = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
InputsAndInjectDependenciesWithKnobs.story = {
|
||||
name: 'inputs and inject dependencies with knobs',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
InputsAndInjectDependenciesWithKnobs.storyName = 'inputs and inject dependencies with knobs';
|
||||
InputsAndInjectDependenciesWithKnobs.decorators = [withKnobs];
|
||||
|
@ -8,6 +8,4 @@ export const ComponentWithStyles = () => ({
|
||||
component: StyledComponent,
|
||||
});
|
||||
|
||||
ComponentWithStyles.story = {
|
||||
name: 'Component with styles',
|
||||
};
|
||||
ComponentWithStyles.storyName = 'Component with styles';
|
||||
|
@ -22,7 +22,5 @@ export const PassedToStory = (_args, { parameters: { fileName, ...parameters } }
|
||||
},
|
||||
});
|
||||
|
||||
PassedToStory.story = {
|
||||
name: 'passed to story',
|
||||
parameters: { storyParameter },
|
||||
};
|
||||
PassedToStory.storyName = 'passed to story';
|
||||
PassedToStory.parameters = { storyParameter };
|
||||
|
@ -23,9 +23,7 @@ export const Simple = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
Simple.story = {
|
||||
name: 'Simple',
|
||||
};
|
||||
Simple.storyName = 'Simple';
|
||||
|
||||
export const WithKnobsStory = () => ({
|
||||
component: NameComponent,
|
||||
@ -34,7 +32,5 @@ export const WithKnobsStory = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
WithKnobsStory.story = {
|
||||
name: 'With Knobs',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
WithKnobsStory.storyName = 'With Knobs';
|
||||
WithKnobsStory.decorators = [withKnobs];
|
||||
|
@ -23,9 +23,7 @@ export const Simple = () => ({
|
||||
},
|
||||
});
|
||||
|
||||
Simple.story = {
|
||||
name: 'Simple',
|
||||
};
|
||||
Simple.storyName = 'Simple';
|
||||
|
||||
export const WithKnobsStory = () => {
|
||||
const name = text('name', 'Dynamic knob');
|
||||
@ -38,7 +36,5 @@ export const WithKnobsStory = () => {
|
||||
};
|
||||
};
|
||||
|
||||
WithKnobsStory.story = {
|
||||
name: 'With knobs',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
WithKnobsStory.storyName = 'With knobs';
|
||||
WithKnobsStory.decorators = [withKnobs];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user