Merge pull request #3697 from Keraito/info-params

Use parameters for info addon
This commit is contained in:
Filipp Riabchun 2018-06-09 20:40:34 +02:00 committed by GitHub
commit 4a250fb7da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1387 additions and 117 deletions

View File

@ -25,102 +25,155 @@ npm i -D @storybook/addon-info
```
## Basic usage
Then wrap your story with the `withInfo`, which is a function that takes either
documentation text or an options object:
```js
import { withInfo } from '@storybook/addon-info';
storiesOf('Component', module)
.add('simple info',
withInfo(`
description or documentation about my component, supports markdown
~~~js
<Button>Click Here</Button>
~~~
`)(() =>
<Component>Click the "?" mark at top-right to view the info.</Component>
)
)
```
## Usage with options
`withInfo` can also take an [options object](#global-options) in case you want to configure how
the info panel looks on a per-story basis:
```js
import { withInfo } from '@storybook/addon-info';
storiesOf('Component', module)
.add('simple info',
withInfo({
styles: {
header: {
h1: {
color: 'red'
}
}
},
text: 'String or React Element with docs about my component', // Warning! This option's name will be likely renamed to "summary" in 3.3 release. Follow this PR #1501 for details
// other possible options see in Global options section below
})(() =>
<Component>Click the "?" mark at top-right to view the info.</Component>
)
)
```
The `styles` prop can also accept a function. The default stylesheet is passed as argument:
```js
import { withInfo } from '@storybook/addon-info';
storiesOf('Component', module)
.add('custom info styles using a function',
withInfo({
styles: stylesheet => ({
...stylesheet,
header: {
...stylesheet.header,
h1: {
...stylesheet.header.h1,
color: 'red'
}
}
})
})(() =>
<Component>Click the "?" mark at top-right to view the info.</Component>
)
)
```
## Usage as decorator
It is possible to add infos by default to all components by using a global or story decorator. The drawback is you won't be able to display a distinct info message per story.
Then, add `withInfo` as a decarator to your book of stories.
It is possible to add `info` by default to all or a subsection of stories by using a global or story decorator.
It is important to declare this decorator as **the first decorator**, otherwise it won't work well.
```js
addDecorator((story, context) => withInfo('common info')(story)(context));
addDecorator(withInfo); // Globally in your .storybook/config.js.
```
or
```js
storiesOf('Component', module)
.addDecorator(withInfo) // At your stories directly.
.add(...);
```
## Global options
Then, you can use the `info` parameter to either pass certain options or specific documentation text to your stories.
A complete list of possible configurations can be found at [in a later section](#setting-global-options).
This can be done per book of stories:
To configure default options for all usage of the info option, use `setDefaults` in `.storybook/config.js`:
```js
import { storiesOf } from '@storybook/react';
import Component from './Component';
storiesOf('Component', module)
.addParameters({
info: {
// Your settings
}
})
.add('with some emoji', () => <Component/>);
```
...or for each story individually:
```js
import { storiesOf } from '@storybook/react';
import Component from './Component';
storiesOf('Component', module)
.add(
'with some emoji',
() => <Component emoji/>,
{ info : { inline: false, header: false } } // Make your component render inline with the additional info
)
.add(
'with no emoji',
() => <Component/>,
{ info: '☹️ no emojis' } // Add additional info text directly
);
```
...or even together:
```js
import { storiesOf } from '@storybook/react';
import Component from './Component';
storiesOf('Component', module)
.addParameters({
info: { // Make a default for all stories in this book,
inline: true, // where the components are inlined
styles: {
header: {
h1: {
color: 'red' // and the headers of the sections are red.
}
}
},
}
})
.add(
'green version',
() => <Component green/>,
{
info: {
styles: stylesheet => ({ // Setting the style with a function
...stylesheet,
header: {
...stylesheet.header,
h1: {
...stylesheet.header.h1,
color: 'green' // Still inlined but with green headers!
}
}
})
}
})
.add(
'something else',
() => <Component different/>,
{
info: "This story has additional text added to the info!" // Still inlined and with red headers!
}
);
```
It is also possible to disable the `info` addon entirely.
Depending on the scope at which you want to disable the addon, pass the following parameters object either to an individual story or to an `addParameters` call.
```
{
info: {
disable: true
}
}
```
## Markdown
The `info` addon also supports markdown.
To use markdown as additional textual documentation for your stories, either pass it directly as a String to the `info` parameters, or use the `text` option.
```js
storiesOf('Button', module)
.add(
'Button Component',
() => <Button />,
{
info: {
text: `
description or documentation about my component, supports markdown
~~~js
<Button>Click Here</Button>
~~~
`
}
}
);
```
## Setting Global Options
To configure default options for all usage of the info addon, pass a option object along with the decorator in `.storybook/config.js`.
```js
// config.js
import { setDefaults } from '@storybook/addon-info';
import { withInfo } from '@storybook/addon-info';
// addon-info
setDefaults({
header: false, // Toggles display of header with component name and description
});
addDecorator(withInfo({
header: false, // Global configuration for the info addon across all of your stories.
}));
```
Configuration parameters can be set at 3 different locations: passed as default options along the `addDecorator` call, passed as an object of parameters to a book of stories to the `addParameters` call, and passed as direct parameters to each individual story.
In order, all of them will be combined together, with a later call overriding the previous set configurations on a per-key basis.
## Options and Defaults
```js
@ -141,24 +194,6 @@ setDefaults({
}
```
## Customizing defaults
To customize your defaults:
```js
// config.js
import { setDefaults } from '@storybook/addon-info';
// addon-info
setDefaults({
inline: true,
maxPropsIntoLine: 1,
maxPropObjectKeys: 10,
maxPropArrayLength: 10,
maxPropStringLength: 100,
});
```
### Rendering a Custom Table
The `TableComponent` option allows you to define how the prop table should be rendered. Your component will be rendered with the following props.

View File

@ -13,6 +13,7 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/addons": "4.0.0-alpha.8",
"@storybook/client-logger": "4.0.0-alpha.8",
"@storybook/components": "4.0.0-alpha.8",
"babel-runtime": "^6.26.0",
@ -24,7 +25,8 @@
"prop-types": "^15.6.1",
"react-addons-create-fragment": "^15.5.3",
"react-emotion": "^9.1.3",
"react-lifecycles-compat": "^3.0.4"
"react-lifecycles-compat": "^3.0.4",
"util-deprecate": "^1.0.2"
},
"devDependencies": {
"react-test-renderer": "^16.4.0"

View File

@ -55,7 +55,7 @@ exports[`addon Info should render <Info /> and external markdown 1`] = `
transform: translateY(-100%) translateY(-6px);
}
<Component>
<deprecated>
<Story
PropTable={[Function]}
components={
@ -1299,7 +1299,7 @@ exports[`addon Info should render <Info /> and external markdown 1`] = `
</div>
</div>
</Story>
</Component>
</deprecated>
`;
exports[`addon Info should render <Info /> and markdown 1`] = `
@ -1357,7 +1357,7 @@ exports[`addon Info should render <Info /> and markdown 1`] = `
transform: translateY(-100%) translateY(-6px);
}
<Component>
<deprecated>
<Story
PropTable={[Function]}
components={
@ -2694,5 +2694,5 @@ containing **bold**, *cursive* text, \`code\` and [a link](https://github.com)"
</div>
</div>
</Story>
</Component>
</deprecated>
`;

View File

@ -1,5 +1,7 @@
import React from 'react';
import nestedObjectAssign from 'nested-object-assign';
import deprecate from 'util-deprecate';
import { makeDecorator } from '@storybook/addons';
import { logger } from '@storybook/client-logger';
import Story from './components/Story';
import PropTable from './components/PropTable';
@ -82,13 +84,23 @@ function addInfo(storyFn, context, infoOptions) {
return <Story {...props}>{storyFn(context)}</Story>;
}
export const withInfo = textOrOptions => {
const options = typeof textOrOptions === 'string' ? { text: textOrOptions } : textOrOptions;
return storyFn => context => addInfo(storyFn, context, options);
};
export const withInfo = makeDecorator({
name: 'withInfo',
parameterName: 'info',
wrapper: (getStory, context, { options, parameters }) => {
const storyOptions = parameters || options;
const infoOptions = typeof storyOptions === 'string' ? { text: storyOptions } : storyOptions;
const mergedOptions =
typeof infoOptions === 'string' ? infoOptions : { ...options, ...infoOptions };
return addInfo(getStory, context, mergedOptions);
},
});
export { Story };
export function setDefaults(newDefaults) {
return Object.assign(defaultOptions, newDefaults);
return deprecate(
() => Object.assign(defaultOptions, newDefaults),
'setDefaults is deprecated. Instead, you can pass options into withInfo(options) directly, or use the info parameter.'
)();
}

View File

@ -330,3 +330,59 @@ storiesOf('Addons|Info.Options.maxPropsIntoLine === 3', module).add(
/>
))
);
storiesOf('Addons|Info.Parameters', module)
.addDecorator(
withInfo({
styles: {
header: {
h1: {
color: 'green',
},
},
},
})
)
.addParameters({
info: {
text:
'This text should be displayed on every story and the component should be inlined between description and PropType table',
inline: true, // Displays info inline vs click button to view
},
})
.add('Using paramaters across all stories', () => <BaseButton label="Button" />)
.add(
'Overwriting and extending the parameters and options set stories-wise',
() => <BaseButton label="Button" />,
{
info: {
text: 'Label propType should be excluded',
excludedPropTypes: ['label'],
},
}
)
.add(
'Overwrite the parameters with markdown variable',
() => <BaseButton onClick={action('clicked')} label="Button" />,
{ info: markdownDescription }
)
.add(
'Overwrite the text parameter with markdown inline',
() => <BaseButton onClick={action('clicked')} label="Button" />,
{
info: {
text: `
description or documentation about my component, supports markdown
~~~js
<Button>Click Here</Button>
~~~
`,
},
}
)
.add(
'Disable the addon entirely',
() => <BaseButton onClick={action('clicked')} label="Button" />,
{ info: { disable: true } }
);

View File

@ -105,13 +105,27 @@ export default class ClientApi {
const fileName = m ? m.id : null;
// Add the fully decorated getStory function.
this._storyStore.addStory(kind, storyName, this._decorateStory(getStory, decorators), {
...this._globalParameters,
...localParameters,
...parameters,
fileName,
const allParam = { fileName };
[this._globalParameters, localParameters, parameters].forEach(params => {
if (params) {
Object.keys(params).forEach(key => {
if (typeof params[key] === 'object') {
allParam[key] = { ...allParam[key], ...params[key] };
} else {
allParam[key] = params[key];
}
});
}
});
// Add the fully decorated getStory function.
this._storyStore.addStory(
kind,
storyName,
this._decorateStory(getStory, decorators),
allParam
);
return api;
};