From 9974a3bc1d510267a33771dddfc6f01716f97e63 Mon Sep 17 00:00:00 2001 From: Alexandre BODIN Date: Wed, 14 Jun 2017 17:04:27 +0200 Subject: [PATCH 1/4] Add support for vue in addon-notes --- addons/notes/src/vue/index.js | 26 +++++++++++++++++++ examples/vue/.storybook/addons.js | 2 ++ examples/vue/package.json | 1 + examples/vue/src/stories/index.js | 43 ++++++++++++++++++++++++++++--- 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 addons/notes/src/vue/index.js diff --git a/addons/notes/src/vue/index.js b/addons/notes/src/vue/index.js new file mode 100644 index 000000000000..0656c1d75b37 --- /dev/null +++ b/addons/notes/src/vue/index.js @@ -0,0 +1,26 @@ +import addons from '@storybook/addons'; + +export const withNotes = ({ notes, component: story }) => { + const channel = addons.getChannel(); + + return { + created() { + channel.emit('storybook/notes/add_notes', notes); + }, + render(h) { + + let component = story; + if (typeof story === 'function') { + component = story(); + } + + if (typeof component === 'string') { + component = { template: component }; + } else if (typeof component === 'function') { + component = { render: component }; + } + + return h(component); + } + } +}; diff --git a/examples/vue/.storybook/addons.js b/examples/vue/.storybook/addons.js index 6aed412d04af..b5d5f6038d54 100644 --- a/examples/vue/.storybook/addons.js +++ b/examples/vue/.storybook/addons.js @@ -1,2 +1,4 @@ import '@storybook/addon-actions/register'; import '@storybook/addon-links/register'; +import '@storybook/addon-notes/register'; + diff --git a/examples/vue/package.json b/examples/vue/package.json index 2856011ceff0..844e5ffbc210 100644 --- a/examples/vue/package.json +++ b/examples/vue/package.json @@ -8,6 +8,7 @@ "@storybook/addon-actions": "^3.0.0", "@storybook/addon-links": "^3.0.0", "@storybook/addons": "^3.0.0", + "@storybook/addon-notes": "^3.0.0", "vue-hot-reload-api": "^2.1.0", "vue-style-loader": "^3.0.1", "vue-loader": "^12.2.1" diff --git a/examples/vue/src/stories/index.js b/examples/vue/src/stories/index.js index e4945ecaec45..2763f5eb03c1 100644 --- a/examples/vue/src/stories/index.js +++ b/examples/vue/src/stories/index.js @@ -5,11 +5,10 @@ import { storiesOf } from '@storybook/vue'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; +import { withNotes } from '@storybook/addon-notes/dist/vue'; + import MyButton from './Button.vue'; -// This does not work. We need to Vue.use or Vue.component is called before mount the root Vue -// Vue.use(Vuex); -// Vue.component('my-button', MyButton); storiesOf('Button', module) // Works if Vue.component is called in the config.js in .storybook @@ -75,3 +74,41 @@ storiesOf('Other', module) action: linkTo('Button') } }) + + +storiesOf('Addon Notes', module) + .add('with some emoji', () => withNotes({ + notes: 'My notes', + component: '

🤔😳😯😮

' + })) + .add('with some button', () => withNotes({ + notes: 'My notes on some button', + component: { + components: { MyButton }, + template: 'rounded' + } + })) + .add('with some color', withNotes({ + notes: 'Some notes on some colored component', + component: { + render(h) { + return h(MyButton, { props: { color: 'pink' } }, ['colorful']); + } + } + })) + .add('with some text', withNotes({ + notes: 'My notes on some text', + component: () => ({ + template: '
Text
' + }) + })) + .add('with some long text', withNotes({ + notes: 'My notes on some long text', + component: () => '
A looooooooonnnnnnnggggggggggggg text
' + })) + .add('with some bold text', withNotes({ + notes: 'My notes on some bold text', + component: () => ({ + render: h => h('div', [h('strong', ['A very long text to display'])]) + }) + })); \ No newline at end of file From bf00a9a6ed53034d4fce52e55b10083f1a3a0c19 Mon Sep 17 00:00:00 2001 From: Alexandre BODIN Date: Wed, 14 Jun 2017 18:37:25 +0200 Subject: [PATCH 2/4] Make addon notes agnostic --- addons/notes/package.json | 19 +---- addons/notes/src/index.js | 25 ++----- addons/notes/src/vue/index.js | 26 ------- app/vue/src/client/preview/client_api.js | 13 +--- app/vue/src/client/preview/render.js | 20 ++++-- examples/cra-storybook/.storybook/addons.js | 1 + examples/cra-storybook/package.json | 1 + examples/cra-storybook/src/stories/index.js | 11 +++ examples/vue/src/stories/index.js | 77 +++++++++------------ 9 files changed, 68 insertions(+), 125 deletions(-) delete mode 100644 addons/notes/src/vue/index.js diff --git a/addons/notes/package.json b/addons/notes/package.json index 188ab8eafc30..0fa8818ea241 100644 --- a/addons/notes/package.json +++ b/addons/notes/package.json @@ -4,8 +4,8 @@ "description": "Write notes for your Storybook stories.", "keywords": [ "addon", - "react", - "storybook" + "storybook", + "notes" ], "license": "MIT", "main": "dist/index.js", @@ -20,19 +20,6 @@ }, "dependencies": { "@storybook/addons": "^3.1.2", - "babel-runtime": "^6.23.0", - "prop-types": "^15.5.10" - }, - "devDependencies": { - "git-url-parse": "^6.2.2", - "react": "^15.5.4", - "react-addons-test-utils": "^15.5.1", - "react-dom": "^15.5.4" - }, - "peerDependencies": { - "react": "*" - }, - "optionalDependencies": { - "@types/react": "^15.0.24" + "babel-runtime": "^6.23.0" } } diff --git a/addons/notes/src/index.js b/addons/notes/src/index.js index 818e3ffb39f3..fa50df85d1bc 100644 --- a/addons/notes/src/index.js +++ b/addons/notes/src/index.js @@ -1,24 +1,11 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import addons from '@storybook/addons'; -export class WithNotes extends React.Component { - render() { - const { children, notes } = this.props; - const channel = addons.getChannel(); +export const withNotes = ({ notes }) => { + const channel = addons.getChannel(); + // send the notes to the channel. - // send the notes to the channel. + return getStory => () => { channel.emit('storybook/notes/add_notes', notes); - // return children elements. - return children; - } -} - -WithNotes.propTypes = { - children: PropTypes.node, - notes: PropTypes.string, -}; -WithNotes.defaultProps = { - children: null, - notes: '', + return getStory(); + }; }; diff --git a/addons/notes/src/vue/index.js b/addons/notes/src/vue/index.js deleted file mode 100644 index 0656c1d75b37..000000000000 --- a/addons/notes/src/vue/index.js +++ /dev/null @@ -1,26 +0,0 @@ -import addons from '@storybook/addons'; - -export const withNotes = ({ notes, component: story }) => { - const channel = addons.getChannel(); - - return { - created() { - channel.emit('storybook/notes/add_notes', notes); - }, - render(h) { - - let component = story; - if (typeof story === 'function') { - component = story(); - } - - if (typeof component === 'string') { - component = { template: component }; - } else if (typeof component === 'function') { - component = { render: component }; - } - - return h(component); - } - } -}; diff --git a/app/vue/src/client/preview/client_api.js b/app/vue/src/client/preview/client_api.js index c930157212be..0e166971d34b 100644 --- a/app/vue/src/client/preview/client_api.js +++ b/app/vue/src/client/preview/client_api.js @@ -59,17 +59,6 @@ export default class ClientApi { throw new Error(`Story of "${kind}" named "${storyName}" already exists`); } - let component = getStory; - if (typeof getStory === 'function') { - component = getStory(); - } - - if (typeof component === 'string') { - component = { template: component }; - } else if (typeof component === 'function') { - component = { render: component }; - } - // Wrap the getStory function with each decorator. The first // decorator will wrap the story function. The second will // wrap the first decorator and so on. @@ -77,7 +66,7 @@ export default class ClientApi { const fn = decorators.reduce( (decorated, decorator) => context => decorator(() => decorated(context), context), - component + getStory ); // Add the fully decorated getStory function. diff --git a/app/vue/src/client/preview/render.js b/app/vue/src/client/preview/render.js index f69910c453c7..80894d8f2c1a 100644 --- a/app/vue/src/client/preview/render.js +++ b/app/vue/src/client/preview/render.js @@ -82,12 +82,20 @@ export function renderMain(data, storyStore) { // ReactDOM.unmountComponentAtNode(rootEl); } - // const context = { - // kind: selectedKind, - // story: selectedStory, - // }; + const context = { + kind: selectedKind, + story: selectedStory, + }; - // const element = story(context); + const element = story(context); + + + let component = element; + if (typeof component === 'string') { + component = { template: component }; + } else if (typeof component === 'function') { + component = { render: component }; + } // if (!element) { // const error = { @@ -112,7 +120,7 @@ export function renderMain(data, storyStore) { // } // ReactDOM.render(element, rootEl); - app.renderStory(story); + app.renderStory(component); return null; } diff --git a/examples/cra-storybook/.storybook/addons.js b/examples/cra-storybook/.storybook/addons.js index 09eddda4c251..3610fa6e48f6 100644 --- a/examples/cra-storybook/.storybook/addons.js +++ b/examples/cra-storybook/.storybook/addons.js @@ -1,3 +1,4 @@ import '@storybook/addon-actions/register'; import '@storybook/addon-links/register'; import '@storybook/addon-events/register'; +import '@storybook/addon-notes/register'; diff --git a/examples/cra-storybook/package.json b/examples/cra-storybook/package.json index 29ba51e8cbf3..1ec726e575b0 100644 --- a/examples/cra-storybook/package.json +++ b/examples/cra-storybook/package.json @@ -22,6 +22,7 @@ "@storybook/addon-actions": "^3.0.0", "@storybook/addon-links": "^3.0.0", "@storybook/addon-events": "^3.0.0", + "@storybook/addon-notes": "^3.0.0", "@storybook/addons": "^3.0.0", "@storybook/react": "^3.0.0", "react-scripts": "1.0.1" diff --git a/examples/cra-storybook/src/stories/index.js b/examples/cra-storybook/src/stories/index.js index e6344a41bb90..77ff2fd0f85f 100644 --- a/examples/cra-storybook/src/stories/index.js +++ b/examples/cra-storybook/src/stories/index.js @@ -4,6 +4,7 @@ import EventEmiter from 'eventemitter3'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; +import { withNotes } from '@storybook/addon-notes'; import { linkTo } from '@storybook/addon-links'; import WithEvents from '@storybook/addon-events'; @@ -88,3 +89,13 @@ storiesOf('WithEvents', module) ) .add('Logger', () => ); + +storiesOf('withNotes', module) + .add('with some text', withNotes({ notes: 'Hello guys' })(() =>
Hello copain
)) + .add('with some emoji', withNotes({ notes: 'My notes on emojies' })(() =>

🤔😳😯😮

)) + .add( + 'with a button and some emoji', + withNotes({ notes: 'My notes on a button with emojies' })(() => + + ) + ); diff --git a/examples/vue/src/stories/index.js b/examples/vue/src/stories/index.js index 2763f5eb03c1..e315a2edb731 100644 --- a/examples/vue/src/stories/index.js +++ b/examples/vue/src/stories/index.js @@ -1,3 +1,4 @@ +import React from 'react'; import Vue from 'vue'; import Vuex from 'vuex'; import { storiesOf } from '@storybook/vue'; @@ -5,14 +6,13 @@ import { storiesOf } from '@storybook/vue'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { withNotes } from '@storybook/addon-notes/dist/vue'; +import { withNotes } from '@storybook/addon-notes'; import MyButton from './Button.vue'; storiesOf('Button', module) // Works if Vue.component is called in the config.js in .storybook - .add('rounded markup only', 'rounded markup only') .add('story as a function template', () => 'story as a function template') .add('story as a function renderer', () => (h) => h('div', ['story as a function renderer'])) .add('story as a function component with template', () => ({ @@ -21,7 +21,7 @@ storiesOf('Button', module) .add('story as a function component with renderer', () => ({ render: (h) => h('my-button', { props : { rounded: true }}, ['story as a function component with renderer']), })) - .add('with vuex', { + .add('with vuex',() => ({ components: { MyButton }, template: 'with vuex: {{ $store.state.count }}', store: new Vuex.Store({ @@ -38,8 +38,8 @@ storiesOf('Button', module) this.$store.commit('increment'); }, }, - }) - .add('with text', { + })) + .add('with text', () => ({ // need to register local component until we can make sur Vue.componennt si called before mounting the root Vue components: { MyButton }, template: 'with text: {{ count }}', @@ -53,62 +53,47 @@ storiesOf('Button', module) this.action(this.count); } } - }) + })); storiesOf('Other', module) - .add('button with emoji', '') - .add('p with emoji', '

🤔😳😯😮

') - .add('colorful', { + .add('button with emoji', () => '') + .add('p with emoji', () => '

🤔😳😯😮

') + .add('colorful', () => ({ render(h) { return h(MyButton, { props: { color: 'pink' } }, ['colorful']); } - }) - .add('rounded', { + })) + .add('rounded', () => ({ components: { MyButton }, template: 'rounded' - }) - .add('not rounded', { + })) + .add('not rounded', () => ({ components: { MyButton }, template: 'not rounded', methods: { action: linkTo('Button') } - }) + })) storiesOf('Addon Notes', module) - .add('with some emoji', () => withNotes({ - notes: 'My notes', - component: '

🤔😳😯😮

' - })) - .add('with some button', () => withNotes({ - notes: 'My notes on some button', - component: { - components: { MyButton }, - template: 'rounded' - } - })) - .add('with some color', withNotes({ - notes: 'Some notes on some colored component', - component: { - render(h) { - return h(MyButton, { props: { color: 'pink' } }, ['colorful']); - } + .add('with some emoji', withNotes({notes: 'My notes on emojies'})(() => '

🤔😳😯😮

')) + .add('with some button', withNotes({ notes: 'My notes on some button' })(() => ({ + components: { MyButton }, + template: 'rounded' + }))) + .add('with some color', withNotes({ notes: 'Some notes on some colored component' })(() => ({ + render(h) { + return h(MyButton, { props: { color: 'pink' } }, ['colorful']); } - })) - .add('with some text', withNotes({ - notes: 'My notes on some text', - component: () => ({ + }))) + .add('with some text', withNotes({ notes: 'My notes on some text' })(() => ({ template: '
Text
' }) - })) - .add('with some long text', withNotes({ - notes: 'My notes on some long text', - component: () => '
A looooooooonnnnnnnggggggggggggg text
' - })) - .add('with some bold text', withNotes({ - notes: 'My notes on some bold text', - component: () => ({ - render: h => h('div', [h('strong', ['A very long text to display'])]) - }) - })); \ No newline at end of file + )) + .add('with some long text', withNotes({ notes: 'My notes on some long text' })( + () => '
A looooooooonnnnnnnggggggggggggg text
' + )) + .add('with some bold text', withNotes({ notes: 'My notes on some bold text' })(() => ({ + render: h => h('div', [h('strong', ['A very long text to display'])]) + }))); \ No newline at end of file From 514f4b775ccd90d53b89678d003ea32e5513c07e Mon Sep 17 00:00:00 2001 From: Alexandre BODIN Date: Wed, 14 Jun 2017 23:19:44 +0200 Subject: [PATCH 3/4] deprecate old WithNotes but keep backward compatible --- addons/notes/README.md | 10 ++------- addons/notes/package.json | 5 ++++- addons/notes/src/index.js | 11 ++++++++++ addons/notes/src/react.js | 24 +++++++++++++++++++++ examples/cra-storybook/src/stories/index.js | 7 +++++- 5 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 addons/notes/src/react.js diff --git a/addons/notes/README.md b/addons/notes/README.md index 94826bc20f08..dffefb10732a 100644 --- a/addons/notes/README.md +++ b/addons/notes/README.md @@ -31,17 +31,11 @@ import '@storybook/addon-notes/register'; Then write your stories like this: ```js -import React from 'react'; - import { storiesOf } from '@storybook/react'; -import { WithNotes } from '@storybook/addon-notes'; +import { withNotes } from '@storybook/addon-notes'; import Component from './Component'; storiesOf('Component', module) - .add('with some emoji', () => ( - - - - )); + .add('with some emoji', withNotes({ notes: 'A very simple component'})(() => )); ``` diff --git a/addons/notes/package.json b/addons/notes/package.json index 0fa8818ea241..1a6f2d8c0be2 100644 --- a/addons/notes/package.json +++ b/addons/notes/package.json @@ -20,6 +20,9 @@ }, "dependencies": { "@storybook/addons": "^3.1.2", - "babel-runtime": "^6.23.0" + "babel-runtime": "^6.23.0", + "prop-types": "^15.5.10", + "react": "^15.5.4", + "util-deprecate": "^1.0.2" } } diff --git a/addons/notes/src/index.js b/addons/notes/src/index.js index fa50df85d1bc..35bc9c6b8587 100644 --- a/addons/notes/src/index.js +++ b/addons/notes/src/index.js @@ -1,4 +1,6 @@ +import deprecate from 'util-deprecate'; import addons from '@storybook/addons'; +import { WithNotes as ReactWithNotes } from './react'; export const withNotes = ({ notes }) => { const channel = addons.getChannel(); @@ -9,3 +11,12 @@ export const withNotes = ({ notes }) => { return getStory(); }; }; + +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' + ), +}); diff --git a/addons/notes/src/react.js b/addons/notes/src/react.js new file mode 100644 index 000000000000..818e3ffb39f3 --- /dev/null +++ b/addons/notes/src/react.js @@ -0,0 +1,24 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import addons from '@storybook/addons'; + +export class WithNotes extends React.Component { + render() { + const { children, notes } = this.props; + const channel = addons.getChannel(); + + // send the notes to the channel. + channel.emit('storybook/notes/add_notes', notes); + // return children elements. + return children; + } +} + +WithNotes.propTypes = { + children: PropTypes.node, + notes: PropTypes.string, +}; +WithNotes.defaultProps = { + children: null, + notes: '', +}; diff --git a/examples/cra-storybook/src/stories/index.js b/examples/cra-storybook/src/stories/index.js index 77ff2fd0f85f..6beb3011278e 100644 --- a/examples/cra-storybook/src/stories/index.js +++ b/examples/cra-storybook/src/stories/index.js @@ -4,7 +4,7 @@ import EventEmiter from 'eventemitter3'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; -import { withNotes } from '@storybook/addon-notes'; +import { withNotes, WithNotes } from '@storybook/addon-notes'; import { linkTo } from '@storybook/addon-links'; import WithEvents from '@storybook/addon-events'; @@ -98,4 +98,9 @@ storiesOf('withNotes', module) withNotes({ notes: 'My notes on a button with emojies' })(() => ) + ) + .add('with old API', () => + + + ); From 5a6472d7519cbbab473c2d02d3d3ebb95cfb9e52 Mon Sep 17 00:00:00 2001 From: Alexandre BODIN Date: Wed, 14 Jun 2017 23:23:16 +0200 Subject: [PATCH 4/4] Cleaning up deps and comments --- addons/notes/package.json | 12 ++++++++++-- addons/notes/src/index.js | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/addons/notes/package.json b/addons/notes/package.json index 1a6f2d8c0be2..b89ba06f1654 100644 --- a/addons/notes/package.json +++ b/addons/notes/package.json @@ -21,8 +21,16 @@ "dependencies": { "@storybook/addons": "^3.1.2", "babel-runtime": "^6.23.0", - "prop-types": "^15.5.10", - "react": "^15.5.4", "util-deprecate": "^1.0.2" + }, + "devDependencies": { + "prop-types": "^15.5.10", + "react": "^15.5.4" + }, + "peerDependencies": { + "react": "*" + }, + "optionalDependencies": { + "@types/react": "^15.0.24" } } diff --git a/addons/notes/src/index.js b/addons/notes/src/index.js index 35bc9c6b8587..7aff6cb5cbf4 100644 --- a/addons/notes/src/index.js +++ b/addons/notes/src/index.js @@ -4,9 +4,9 @@ import { WithNotes as ReactWithNotes } from './react'; export const withNotes = ({ notes }) => { const channel = addons.getChannel(); - // send the notes to the channel. return getStory => () => { + // send the notes to the channel before the story is rendered channel.emit('storybook/notes/add_notes', notes); return getStory(); };