Merge pull request #3373 from storybooks/tmeasday/use-parameters-in-addons

Use per-story parameters in Notes addon
This commit is contained in:
Filipp Riabchun 2018-04-14 01:45:44 +02:00 committed by GitHub
commit 80c4bf57b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 181 additions and 140 deletions

View File

@ -7,7 +7,7 @@
[![Storybook Slack](https://now-examples-slackin-rrirkqohko.now.sh/badge.svg)](https://now-examples-slackin-rrirkqohko.now.sh/)
[![Backers on Open Collective](https://opencollective.com/storybook/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/storybook/sponsors/badge.svg)](#sponsors)
* * *
---
Storybook Addon Notes allows you to write notes (text or HTML) for your stories in [Storybook](https://storybook.js.org).
@ -29,16 +29,25 @@ Add following content to it:
import '@storybook/addon-notes/register';
```
Then write your stories like this:
Then add the `withNotes` decorator to all stories in your `config.js`:
```js
// Import from @storybook/X where X is your framework
import { configure, addDecorator } from '@storybook/react';
import { withNotes } from '@storybook/addon-notes';
addDecorator(withNotes);
```
You can use the `notes` parameter to add a note to each story:
```js
import { storiesOf } from '@storybook/react';
import { withNotes } from '@storybook/addon-notes';
import Component from './Component';
storiesOf('Component', module)
.add('with some emoji', withNotes('A very simple component')(() => </Component>));
.add('with some emoji', () => </Component>, { notes: 'A very simple component' });
```
#### Using Markdown
@ -47,25 +56,27 @@ To use markdown in your notes simply import a markdown file and use that in your
```js
import { storiesOf } from '@storybook/react';
import { withNotes } from '@storybook/addon-notes';
import Component from './Component';
import someMarkdownText from './someMarkdownText.md';
storiesOf('Component', module)
.add('With Markdown', withNotes(someMarkdownText)(() => <Component/>));
storiesOf('Component', module).add(
'With Markdown',
() => <Component />
{ notes: someMarkdownText }
);
```
If you want to use Github flavored markdown inline, use `withMarkdownNotes`:
If you want to use Github flavored markdown inline, use `notes: { markdownText: 'your md' }`:
```js
import { storiesOf } from '@storybook/react';
import { withMarkdownNotes } from '@storybook/addon-notes';
import Component from './Component';
storiesOf('Component', module)
.add('With Markdown', withMarkdownNotes(`
# Hello World
storiesOf('Component', module).add(
'With Markdown',
() => <Component />
{ notes: { markdown: `
# Hello World
This is some code showing usage of the component and other inline documentation
@ -75,20 +86,6 @@ This is some code showing usage of the component and other inline documentation
<Component/>
</div>
~~~
`)(() => <Component/>));
```
### Deprecated API
This API is slated for removal in 4.0
```js
import { WithNotes } from '@storybook/addon-notes';
storiesOf('Addon Notes', module)
.add('using deprecated API', () => (
<WithNotes notes="Hello">
<BaseButton onClick={action('clicked')} label="😀 😎 👍 💯" />
</WithNotes>
));
`} }
);
```

View File

@ -4,12 +4,39 @@ import { withNotes } from '..';
jest.mock('@storybook/addons');
describe('Storybook Addon Notes', () => {
it('should inject info', () => {
it('should inject text from `notes` parameter', () => {
const channel = { emit: jest.fn() };
addons.getChannel.mockReturnValue(channel);
const getStory = jest.fn();
const context = {};
const context = { parameters: { notes: 'hello' } };
withNotes(getStory, context);
expect(channel.emit).toHaveBeenCalledWith('storybook/notes/add_notes', 'hello');
expect(getStory).toHaveBeenCalledWith(context);
});
it('should inject markdown from `notes.markdown` parameter', () => {
const channel = { emit: jest.fn() };
addons.getChannel.mockReturnValue(channel);
const getStory = jest.fn();
const context = { parameters: { notes: { markdown: '# hello' } } };
withNotes(getStory, context);
expect(channel.emit).toHaveBeenCalledWith(
'storybook/notes/add_notes',
expect.stringContaining('<h1 id="hello">hello</h1>')
);
expect(getStory).toHaveBeenCalledWith(context);
});
it('should inject info (deprecated API)', () => {
const channel = { emit: jest.fn() };
addons.getChannel.mockReturnValue(channel);
const getStory = jest.fn();
const context = { parameters: {} };
const decoratedStory = withNotes('hello')(getStory);
decoratedStory(context);

View File

@ -1,34 +1,46 @@
import deprecate from 'util-deprecate';
import addons from '@storybook/addons';
import marked from 'marked';
import { WithNotes as ReactWithNotes } from './react';
export const withMarkdownNotes = (text, options) => {
function renderMarkdown(text, options) {
marked.setOptions({ ...marked.defaults, options });
return marked(text);
}
const decorator = options => {
const channel = addons.getChannel();
return getStory => context => {
marked.setOptions({ ...marked.defaults, options });
// send the notes to the channel before the story is rendered
channel.emit('storybook/notes/add_notes', marked(text));
return (getStory, context) => {
const { parameters: { notes } } = context;
const storyOptions = notes || options;
if (storyOptions) {
const { text, markdown, markdownOptions } =
typeof storyOptions === 'string' ? { text: storyOptions } : storyOptions;
if (!text && !markdown) {
throw new Error('You must set of one of `text` or `markdown` on the `notes` parameter');
}
channel.emit('storybook/notes/add_notes', text || renderMarkdown(markdown, markdownOptions));
}
return getStory(context);
};
};
export const withNotes = textOrOptions => {
const channel = addons.getChannel();
const options = typeof textOrOptions === 'string' ? { text: textOrOptions } : textOrOptions;
const hoc = options => story => context => decorator(options)(story, context);
return getStory => context => {
// send the notes to the channel before the story is rendered
channel.emit('storybook/notes/add_notes', options.text);
return getStory(context);
};
export const withMarkdownNotes = (text, options) =>
hoc({
markdown: text,
markdownOptions: options,
});
export const withNotes = (...args) => {
// Used without options as .addDecorator(withNotes)
if (typeof args[0] === 'function') {
return decorator()(...args);
}
// Input are options, ala .add('name', withNotes('note')(() => <Story/>))
return hoc(args[0]);
};
Object.defineProperty(exports, 'WithNotes', {
configurable: true,
enumerable: true,
get: deprecate(
() => ReactWithNotes,
'@storybook/addon-notes WithNotes Component is deprecated, use withNotes() instead. See https://github.com/storybooks/storybook/tree/master/addons/notes'
),
});

View File

@ -44,7 +44,7 @@ export function renderMain(data, storyStore, forceRender) {
const noPreview = <NoPreview />;
const { selectedKind, selectedStory } = data;
const story = storyStore.getStory(selectedKind, selectedStory);
const story = storyStore.getStoryWithContext(selectedKind, selectedStory);
if (!story) {
m.mount(rootEl, { view: () => noPreview });
return;
@ -57,12 +57,7 @@ export function renderMain(data, storyStore, forceRender) {
previousKind = selectedKind;
previousStory = selectedStory;
const context = {
kind: selectedKind,
story: selectedStory,
};
const element = story(context);
const element = story();
if (!element) {
const error = {

View File

@ -3,31 +3,34 @@ import { withNotes } from '@storybook/addon-notes';
import { Button } from '@storybook/angular/demo';
storiesOf('Addon|Notes', module)
.addDecorator(withNotes)
.add(
'Simple note',
withNotes({ text: 'My notes on some button' })(() => ({
() => ({
component: Button,
props: {
text: 'Notes on some Button',
onClick: () => {},
},
}))
}),
{ notes: 'My notes on some button' }
)
.add(
'Note with HTML',
withNotes({
text: `
() => ({
component: Button,
props: {
text: 'Notes with HTML',
onClick: () => {},
},
}),
{
notes: `
<h2>My notes on emojis</h2>
<em>It's not all that important to be honest, but..</em>
Emojis are great, I love emojis, in fact I like using them in my Component notes too! 😇
`,
})(() => ({
component: Button,
props: {
text: 'Notes with HTML',
onClick: () => {},
},
}))
}
);

View File

@ -3,8 +3,7 @@ import React from 'react';
import { storiesOf } from '@storybook/react';
import { setOptions } from '@storybook/addon-options';
import { action } from '@storybook/addon-actions';
// eslint-disable-next-line import/named
import { withNotes, WithNotes } from '@storybook/addon-notes';
import { withNotes } from '@storybook/addon-notes';
import centered from '@storybook/addon-centered';
import { withInfo } from '@storybook/addon-info';
import { Button } from '@storybook/react/demo';
@ -32,6 +31,7 @@ const InfoButton = () => (
);
storiesOf('Button', module)
.addDecorator(withNotes)
.add('with text', () => (
<Button onClick={action('clicked')}>
{setOptions({ selectedAddonPanel: 'storybook/actions/actions-panel' })}
@ -46,15 +46,16 @@ storiesOf('Button', module)
</span>
</Button>
))
.add('with notes', () => (
// deprecated usage
<WithNotes notes="A very simple button">
.add(
'with notes',
() => (
<Button>
{setOptions({ selectedAddonPanel: 'storybook/notes/panel' })}
Check my notes in the notes panel
</Button>
</WithNotes>
))
),
{ notes: 'A very simple button' }
)
.addWithInfo(
'with some info',
'Use the [info addon](https://github.com/storybooks/storybook/tree/master/addons/info) with its painful API.',

View File

@ -7,9 +7,10 @@ import { storiesOf } from '@storybook/mithril';
import { withNotes } from '@storybook/addon-notes';
storiesOf('Addons|Notes', module)
.addDecorator(withNotes)
.add(
'Simple note',
withNotes({ text: 'My notes on some bold text' })(() => ({
() => ({
view: () => (
<p>
<strong>
@ -22,19 +23,12 @@ storiesOf('Addons|Notes', module)
</strong>
</p>
),
}))
}),
{ notes: 'My notes on some bold text' }
)
.add(
'Note with HTML',
withNotes({
text: `
<h2>My notes on emojies</h2>
<em>It's not all that important to be honest, but..</em>
Emojis are great, I love emojis, in fact I like using them in my Component notes too! 😇
`,
})(() => ({
() => ({
view: () => (
<p>
<span>🤔😳😯😮</span>
@ -44,5 +38,14 @@ storiesOf('Addons|Notes', module)
<span>🤓😑😶😊</span>
</p>
),
}))
}),
{
notes: `
<h2>My notes on emojies</h2>
<em>It's not all that important to be honest, but..</em>
Emojis are great, I love emojis, in fact I like using them in my Component notes too! 😇
`,
}
);

View File

@ -1,8 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots Addons|Notes using deprecated API 1`] = `
exports[`Storyshots Addons|Notes using decorator arguments, withMarkdownNotes 1`] = `
<button>
😀 😎 👍 💯
Button with notes - check the notes panel for details
</button>
`;
exports[`Storyshots Addons|Notes using decorator arguments, withNotes 1`] = `
<button>
Button with notes - check the notes panel for details
</button>
`;
@ -20,6 +26,6 @@ exports[`Storyshots Addons|Notes withNotes rendering imported markdown 1`] = `
exports[`Storyshots Addons|Notes withNotes rendering inline, github-flavored markdown 1`] = `
<button>
Button with notes from inline github-flavored markdown - check the notes panel for details
Button with notes - check the notes panel for details
</button>
`;

View File

@ -1,28 +1,15 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
// eslint-disable-next-line import/named
import { withNotes, WithNotes, withMarkdownNotes } from '@storybook/addon-notes';
import { action } from '@storybook/addon-actions';
import { withNotes, withMarkdownNotes } from '@storybook/addon-notes';
import BaseButton from '../components/BaseButton';
import markdownNotes from './notes/notes.md';
storiesOf('Addons|Notes', module)
.add(
'withNotes',
withNotes(
'This is the notes for a button. This is helpful for adding details about a story in a separate panel.'
)(() => <BaseButton label="Button with notes - check the notes panel for details" />)
)
.add(
'withNotes rendering imported markdown',
withNotes(markdownNotes)(() => (
<BaseButton label="Button with notes - check the notes panel for details" />
))
)
.add(
'withNotes rendering inline, github-flavored markdown',
withMarkdownNotes(`
const baseStory = () => (
<BaseButton label="Button with notes - check the notes panel for details" />
);
const markdownString = `
# Documentation
This is inline github-flavored markdown!
@ -37,12 +24,20 @@ storiesOf('Addons|Notes', module)
))
)
~~~
`)(() => (
<BaseButton label="Button with notes from inline github-flavored markdown - check the notes panel for details" />
))
)
.add('using deprecated API', () => (
<WithNotes notes="Hello">
<BaseButton onClick={action('clicked')} label="😀 😎 👍 💯" />
</WithNotes>
));
`;
storiesOf('Addons|Notes', module)
.addDecorator(withNotes)
.add('withNotes', baseStory, {
notes:
'This is the notes for a button. This is helpful for adding details about a story in a separate panel.',
})
.add('withNotes rendering imported markdown', baseStory, { notes: markdownNotes })
.add('withNotes rendering inline, github-flavored markdown', baseStory, {
notes: { markdown: markdownString },
})
.add('using decorator arguments, withNotes', withNotes('Notes into withNotes')(baseStory))
.add(
'using decorator arguments, withMarkdownNotes',
withMarkdownNotes(markdownString)(baseStory)
);

View File

@ -2,22 +2,21 @@ import { storiesOf } from '@storybook/polymer';
import { withNotes } from '@storybook/addon-notes';
storiesOf('Addon|Notes', module)
.addDecorator(withNotes)
.add(
'Simple note',
withNotes({ text: 'My notes on some bold text' })(
() =>
'<p><strong>Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam sed vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec consectetur velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus arcu. Nullam sit amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at fermentum. Nulla sollicitudin, mauris quis semper tempus, sem metus tristique diam, efficitur pulvinar mi urna id urna.</strong></p>'
)
() =>
'<p><strong>Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam sed vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec consectetur velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus arcu. Nullam sit amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at fermentum. Nulla sollicitudin, mauris quis semper tempus, sem metus tristique diam, efficitur pulvinar mi urna id urna.</strong></p>',
{
notes: 'My notes on some bold text',
}
)
.add(
'Note with HTML',
withNotes({
text: `
.add('Note with HTML', () => '<p>🤔😳😯😮<br/>😄😩😓😱<br/>🤓😑😶😊</p>', {
notes: `
<h2>My notes on emojies</h2>
<em>It's not all that important to be honest, but..</em>
Emojis are great, I love emojis, in fact I like using them in my Component notes too! 😇
`,
})(() => '<p>🤔😳😯😮<br/>😄😩😓😱<br/>🤓😑😶😊</p>')
);
});

View File

@ -2,24 +2,27 @@ import { storiesOf } from '@storybook/vue';
import { withNotes } from '@storybook/addon-notes';
storiesOf('Addon|Notes', module)
.addDecorator(withNotes)
.add(
'Simple note',
withNotes({ text: 'My notes on some bold text' })(() => ({
() => ({
template:
'<p><strong>Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam sed vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec consectetur velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus arcu. Nullam sit amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at fermentum. Nulla sollicitudin, mauris quis semper tempus, sem metus tristique diam, efficitur pulvinar mi urna id urna.</strong></p>',
}))
}),
{ notes: 'My notes on some bold text' }
)
.add(
'Note with HTML',
withNotes({
text: `
() => ({
template: '<p>🤔😳😯😮<br/>😄😩😓😱<br/>🤓😑😶😊</p>',
}),
{
notes: `
<h2>My notes on emojies</h2>
<em>It's not all that important to be honest, but..</em>
Emojis are great, I love emojis, in fact I like using them in my Component notes too! 😇
`,
})(() => ({
template: '<p>🤔😳😯😮<br/>😄😩😓😱<br/>🤓😑😶😊</p>',
}))
}
);