diff --git a/addons/viewport/README.md b/addons/viewport/README.md index a7817f11070e..78dcae25c40b 100644 --- a/addons/viewport/README.md +++ b/addons/viewport/README.md @@ -188,6 +188,19 @@ storiesOf('Decorator with string', module) )); +// Single +storiesOf('Parameterized story', module) + .addDecorator(withViewport()) + .add( + 'iPad', + () => ( +

+ Do I look good on iPad? +

+ ), + { viewport: 'ipad' } + ); + storiesOf('Decorator with object', module) .addDecorator( withViewport({ diff --git a/addons/viewport/src/preview/withViewport.js b/addons/viewport/src/preview/withViewport.js index 1527080ee021..44a74228c278 100644 --- a/addons/viewport/src/preview/withViewport.js +++ b/addons/viewport/src/preview/withViewport.js @@ -1,4 +1,4 @@ -import addons from '@storybook/addons'; +import addons, { makeDecorator } from '@storybook/addons'; import CoreEvents from '@storybook/core-events'; import deprecate from 'util-deprecate'; @@ -11,36 +11,44 @@ import { function noop() {} let handler = noop; +const callHandler = (...args) => handler(...args) + const subscription = () => { const channel = addons.getChannel(); - channel.on(VIEWPORT_CHANGED_EVENT_ID, handler); - return () => channel.removeListener(VIEWPORT_CHANGED_EVENT_ID, handler); + channel.on(VIEWPORT_CHANGED_EVENT_ID, callHandler); + return () => channel.removeListener(VIEWPORT_CHANGED_EVENT_ID, callHandler); }; -const setViewport = options => { +const applyViewportOptions = (options = {}) => { const channel = addons.getChannel(); + handler = options.onViewportChange || noop; if (options.onViewportChange) { channel.emit(CoreEvents.REGISTER_SUBSCRIPTION, subscription); } + channel.emit(SET_STORY_DEFAULT_VIEWPORT_EVENT_ID, options.name || DEFAULT_VIEWPORT); }; -export default function withViewport(nameOrOptions) { - const options = typeof nameOrOptions === 'string' ? { name: nameOrOptions } : nameOrOptions; +const withViewport = makeDecorator({ + name: 'withViewport', + parameterName: 'viewport', + wrapper: (getStory, context, { options, parameters }) => { + const storyOptions = parameters || options; + const viewportOptions = + typeof storyOptions === 'string' ? { name: storyOptions } : storyOptions; + + if (viewportOptions) { + applyViewportOptions(viewportOptions); + } - return (story, context) => { - const decorated = () => { - setViewport(options); - return story(); - }; + return getStory(context); + }, +}); - // Absent context means a direct call, withViewport(viewport)(storyFn) - return context ? decorated() : decorated; - }; -} +export default withViewport; export const Viewport = deprecate(({ children, ...options }) => { - setViewport(options); + applyViewportOptions(options); return children; -}, ` usage is deprecated, use .addDecorator(withViewport(viewport)) instead`); +}, ` usage is deprecated, use .addParameters({ viewport }) instead`); diff --git a/examples/official-storybook/stories/Logger.js b/examples/official-storybook/stories/Logger.js index 80f2f03fbbf9..4b6571c9ebc0 100644 --- a/examples/official-storybook/stories/Logger.js +++ b/examples/official-storybook/stories/Logger.js @@ -12,7 +12,7 @@ const Wrapper = styled('div')({ const Title = styled('h1')({ margin: 0, }); -const Item = () => ({ +const Item = styled('div')({ listStyle: 'none', marginBottom: 10, }); diff --git a/examples/official-storybook/stories/__snapshots__/addon-viewport.stories.storyshot b/examples/official-storybook/stories/__snapshots__/addon-viewport.stories.storyshot index 67479d9354a9..17da990704e3 100644 --- a/examples/official-storybook/stories/__snapshots__/addon-viewport.stories.storyshot +++ b/examples/official-storybook/stories/__snapshots__/addon-viewport.stories.storyshot @@ -32,7 +32,7 @@ exports[`Storyshots Addons|Viewport.Custom Default (Kindle Fire 2) Overridden vi `; -exports[`Storyshots Addons|Viewport.Custom Default (Kindle Fire 2) Overridden via "withViewport" decorator 1`] = ` +exports[`Storyshots Addons|Viewport.Custom Default (Kindle Fire 2) Overridden via "withViewport" decorator (deprecated) 1`] = `
@@ -44,6 +44,18 @@ exports[`Storyshots Addons|Viewport.Custom Default (Kindle Fire 2) Overridden vi
`; +exports[`Storyshots Addons|Viewport.Custom Default (Kindle Fire 2) Overridden via "withViewport" parameterized decorator 1`] = ` +
+ I respect my parents but I should be looking good on + + iPad + + . +
+`; + exports[`Storyshots Addons|Viewport.withViewport onViewportChange 1`] = `
)) .add( - 'Overridden via "withViewport" decorator', + 'Overridden via "withViewport" parameterized decorator', + () => ( + + I respect my parents but I should be looking good on iPad. + + ), + { viewport: 'ipad' } + ) + .add( + 'Overridden via "withViewport" decorator (deprecated)', withViewport('iphone6')(() => ( I respect my parents but I should be looking good on iPhone 6.