From 9ad87880f2fa2c2c57d53ceb01f490303ae769ab Mon Sep 17 00:00:00 2001 From: Laura Date: Mon, 19 Apr 2021 21:13:56 +1000 Subject: [PATCH 1/5] Fix Source: Dynamic snippets includes decorators --- .../src/frameworks/react/jsxDecorator.test.tsx | 18 ++++++++++++++++++ .../docs/src/frameworks/react/jsxDecorator.tsx | 8 +++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/addons/docs/src/frameworks/react/jsxDecorator.test.tsx b/addons/docs/src/frameworks/react/jsxDecorator.test.tsx index 17ac4e4862eb..b33ed6517d65 100644 --- a/addons/docs/src/frameworks/react/jsxDecorator.test.tsx +++ b/addons/docs/src/frameworks/react/jsxDecorator.test.tsx @@ -183,6 +183,24 @@ describe('jsxDecorator', () => { ); }); + it('should render dynamically when provided a component', () => { + const Component = ({ className }: { className: string }) => ( +
component
+ ); + const storyFn = (args: any) => ; + const context = makeContext( + 'args', + { __isArgsStory: true, component: Component }, + { className: 'test' } + ); + jsxDecorator(storyFn, context); + expect(mockChannel.emit).toHaveBeenCalledWith( + SNIPPET_RENDERED, + 'jsx-test--args', + '' + ); + }); + it('should skip dynamic rendering for no-args stories', () => { const storyFn = () =>
classic story
; const context = makeContext('classic', {}, {}); diff --git a/addons/docs/src/frameworks/react/jsxDecorator.tsx b/addons/docs/src/frameworks/react/jsxDecorator.tsx index 2fbaab94a41b..d4a237f1d56d 100644 --- a/addons/docs/src/frameworks/react/jsxDecorator.tsx +++ b/addons/docs/src/frameworks/react/jsxDecorator.tsx @@ -166,8 +166,14 @@ export const jsxDecorator = (storyFn: any, context: StoryContext) => { ...(context?.parameters.jsx || {}), } as Required; + let storyOrComponent = story; + const { parameters, args } = context; + if (parameters.component) { + storyOrComponent = React.createElement(parameters.component, { ...args }); + } + let jsx = ''; - const rendered = renderJsx(story, options); + const rendered = renderJsx(storyOrComponent, options); if (rendered) { jsx = applyTransformSource(rendered, options, context); } From cf30e79b60d5b45f6ef12db5a41568f75d468b5b Mon Sep 17 00:00:00 2001 From: Laura Date: Tue, 20 Apr 2021 21:35:18 +1000 Subject: [PATCH 2/5] Add decorators example in cra-kitchen-sink --- .../src/frameworks/react/jsxDecorator.tsx | 2 +- .../src/stories/decorators.stories.js | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 examples/cra-kitchen-sink/src/stories/decorators.stories.js diff --git a/addons/docs/src/frameworks/react/jsxDecorator.tsx b/addons/docs/src/frameworks/react/jsxDecorator.tsx index d4a237f1d56d..898f9dc10c4c 100644 --- a/addons/docs/src/frameworks/react/jsxDecorator.tsx +++ b/addons/docs/src/frameworks/react/jsxDecorator.tsx @@ -169,7 +169,7 @@ export const jsxDecorator = (storyFn: any, context: StoryContext) => { let storyOrComponent = story; const { parameters, args } = context; if (parameters.component) { - storyOrComponent = React.createElement(parameters.component, { ...args }); + storyOrComponent = React.createElement(parameters.component, args); } let jsx = ''; diff --git a/examples/cra-kitchen-sink/src/stories/decorators.stories.js b/examples/cra-kitchen-sink/src/stories/decorators.stories.js new file mode 100644 index 000000000000..b5ae58844470 --- /dev/null +++ b/examples/cra-kitchen-sink/src/stories/decorators.stories.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { Button } from '@storybook/react/demo'; + +export default { + title: 'Decorators', + component: Button, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +}; + +export const WithArgs = (args) => ; From 5500a0a42bf08ae4ff7f329ab8ebedb3e6f8f887 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Fri, 23 Apr 2021 09:14:02 +0800 Subject: [PATCH 3/5] Official-storybook: Add useContext example --- .../stories/hooks.stories.js | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/examples/official-storybook/stories/hooks.stories.js b/examples/official-storybook/stories/hooks.stories.js index b9642a674927..a5973d68d926 100644 --- a/examples/official-storybook/stories/hooks.stories.js +++ b/examples/official-storybook/stories/hooks.stories.js @@ -1,8 +1,17 @@ -import React from 'react'; +import React, { useContext, createContext } from 'react'; import { useEffect, useRef, useState } from '@storybook/client-api'; +const Consumer = () => { + // testing hooks in the component itself, + // rendering JSX for the component without decorators + // per https://github.com/storybookjs/storybook/pull/14652/ + const value = useContext(DummyContext); + return
value: {value}
; +}; + export default { title: 'Core/Hooks', + component: Consumer, }; export const Checkbox = () => { @@ -44,3 +53,19 @@ export const ReactHookCheckbox = () => { ); }; + +const DummyContext = createContext({}); + +export const Context = (args) => { + // testing hooks in the story + const storyContext = useContext(DummyContext); + return ; +}; + +Context.decorators = [ + (Story) => ( + + + + ), +]; From cda9cb9b422e9000b5386b1f40aacb7d8b183686 Mon Sep 17 00:00:00 2001 From: Laura Date: Sun, 23 May 2021 17:40:43 +1000 Subject: [PATCH 4/5] Updated based on feedback --- .../src/frameworks/react/jsxDecorator.tsx | 11 ++++----- .../src/stories/decorators.stories.js | 23 +++++++++++++++++++ lib/addons/src/types.ts | 1 + lib/client-api/src/story_store.ts | 4 ++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/addons/docs/src/frameworks/react/jsxDecorator.tsx b/addons/docs/src/frameworks/react/jsxDecorator.tsx index 898f9dc10c4c..c4f9815102f0 100644 --- a/addons/docs/src/frameworks/react/jsxDecorator.tsx +++ b/addons/docs/src/frameworks/react/jsxDecorator.tsx @@ -166,14 +166,13 @@ export const jsxDecorator = (storyFn: any, context: StoryContext) => { ...(context?.parameters.jsx || {}), } as Required; - let storyOrComponent = story; - const { parameters, args } = context; - if (parameters.component) { - storyOrComponent = React.createElement(parameters.component, args); - } + // Exclude decorators from source code snippet by default + const sourceJsx = context?.parameters.docs?.source?.includeDecorators + ? story + : context.originalStoryFn(context.args); let jsx = ''; - const rendered = renderJsx(storyOrComponent, options); + const rendered = renderJsx(sourceJsx, options); if (rendered) { jsx = applyTransformSource(rendered, options, context); } diff --git a/examples/cra-kitchen-sink/src/stories/decorators.stories.js b/examples/cra-kitchen-sink/src/stories/decorators.stories.js index b5ae58844470..c24d4e65b6c3 100644 --- a/examples/cra-kitchen-sink/src/stories/decorators.stories.js +++ b/examples/cra-kitchen-sink/src/stories/decorators.stories.js @@ -1,6 +1,15 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; import { Button } from '@storybook/react/demo'; +import PropTypes from 'prop-types'; + +const Bold = ({ children }) => { + return {children}; +}; + +Bold.propTypes = { + children: PropTypes.string.isRequired, +}; export default { title: 'Decorators', @@ -18,3 +27,17 @@ export const WithArgs = (args) => ; + +export const Nested = (args) => ( + +); +Nested.args = { onClick: action('clicked', { depth: 1 }) }; +Nested.parameters = { + docs: { + source: { + includeDecorators: false, + }, + }, +}; \ No newline at end of file diff --git a/lib/addons/src/types.ts b/lib/addons/src/types.ts index 816f12f674b6..73fdd0563abc 100644 --- a/lib/addons/src/types.ts +++ b/lib/addons/src/types.ts @@ -62,6 +62,7 @@ export type StoryContext = StoryIdentifier & { globals: Args; hooks?: HooksContext; viewMode?: ViewMode; + originalStoryFn: ArgsStoryFn; }; export interface WrapperSettings { diff --git a/lib/client-api/src/story_store.ts b/lib/client-api/src/story_store.ts index 75d064ab7ccf..1ebb3027e4e9 100644 --- a/lib/client-api/src/story_store.ts +++ b/lib/client-api/src/story_store.ts @@ -487,6 +487,7 @@ export default class StoryStore { args: {}, argTypes: {}, globals: {}, + originalStoryFn: getOriginal(), }), }), { __isArgsStory, ...combinedParameters } @@ -506,6 +507,7 @@ export default class StoryStore { argTypes, globals: this._globals, viewMode: this._selection?.viewMode, + originalStoryFn: getOriginal(), }); }; @@ -521,6 +523,7 @@ export default class StoryStore { argTypes, globals: this._globals, viewMode: this._selection?.viewMode, + originalStoryFn: getOriginal(), }; const loadResults = await Promise.all(loaders.map((loader) => loader(context))); const loaded = Object.assign({}, ...loadResults); @@ -554,6 +557,7 @@ export default class StoryStore { args: initialArgsBeforeEnhancers, argTypes, globals: {}, + originalStoryFn: getOriginal(), }), }), initialArgsBeforeEnhancers From a5c667f7e66ba205df4632b4f128321e6937343a Mon Sep 17 00:00:00 2001 From: Laura Date: Mon, 24 May 2021 08:56:46 +1000 Subject: [PATCH 5/5] Updated to excludeDecorator and updated test --- .../frameworks/react/jsxDecorator.test.tsx | 27 ++++++++++++------- .../src/frameworks/react/jsxDecorator.tsx | 6 ++--- .../cra-kitchen-sink/.storybook/preview.js | 5 ++++ .../src/stories/decorators.stories.js | 7 ----- lib/addons/src/types.ts | 2 +- 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/addons/docs/src/frameworks/react/jsxDecorator.test.tsx b/addons/docs/src/frameworks/react/jsxDecorator.test.tsx index b33ed6517d65..6230dddec2ad 100644 --- a/addons/docs/src/frameworks/react/jsxDecorator.test.tsx +++ b/addons/docs/src/frameworks/react/jsxDecorator.test.tsx @@ -155,12 +155,13 @@ describe('renderJsx', () => { }); // @ts-ignore -const makeContext = (name: string, parameters: any, args: any): StoryContext => ({ +const makeContext = (name: string, parameters: any, args: any, extra?: object): StoryContext => ({ id: `jsx-test--${name}`, kind: 'js-text', name, parameters, args, + ...extra, }); describe('jsxDecorator', () => { @@ -183,21 +184,29 @@ describe('jsxDecorator', () => { ); }); - it('should render dynamically when provided a component', () => { - const Component = ({ className }: { className: string }) => ( -
component
+ it('should not render decorators when provided excludeDecorators parameter', () => { + const storyFn = (args: any) =>
args story
; + const decoratedStoryFn = (args: any) => ( +
{storyFn(args)}
); - const storyFn = (args: any) => ; const context = makeContext( 'args', - { __isArgsStory: true, component: Component }, - { className: 'test' } + { + __isArgsStory: true, + docs: { + source: { + excludeDecorators: true, + }, + }, + }, + {}, + { originalStoryFn: storyFn } ); - jsxDecorator(storyFn, context); + jsxDecorator(decoratedStoryFn, context); expect(mockChannel.emit).toHaveBeenCalledWith( SNIPPET_RENDERED, 'jsx-test--args', - '' + '
\n args story\n
' ); }); diff --git a/addons/docs/src/frameworks/react/jsxDecorator.tsx b/addons/docs/src/frameworks/react/jsxDecorator.tsx index c4f9815102f0..8314aff3151b 100644 --- a/addons/docs/src/frameworks/react/jsxDecorator.tsx +++ b/addons/docs/src/frameworks/react/jsxDecorator.tsx @@ -167,9 +167,9 @@ export const jsxDecorator = (storyFn: any, context: StoryContext) => { } as Required; // Exclude decorators from source code snippet by default - const sourceJsx = context?.parameters.docs?.source?.includeDecorators - ? story - : context.originalStoryFn(context.args); + const sourceJsx = context?.parameters.docs?.source?.excludeDecorators + ? context.originalStoryFn(context.args) + : story; let jsx = ''; const rendered = renderJsx(sourceJsx, options); diff --git a/examples/cra-kitchen-sink/.storybook/preview.js b/examples/cra-kitchen-sink/.storybook/preview.js index e484476c0b67..12dea5a460c2 100644 --- a/examples/cra-kitchen-sink/.storybook/preview.js +++ b/examples/cra-kitchen-sink/.storybook/preview.js @@ -5,4 +5,9 @@ addParameters({ storySort: (a, b) => a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id, undefined, { numeric: true }), }, + docs: { + source: { + excludeDecorators: true, + }, + }, }); diff --git a/examples/cra-kitchen-sink/src/stories/decorators.stories.js b/examples/cra-kitchen-sink/src/stories/decorators.stories.js index c24d4e65b6c3..0ea8032620a7 100644 --- a/examples/cra-kitchen-sink/src/stories/decorators.stories.js +++ b/examples/cra-kitchen-sink/src/stories/decorators.stories.js @@ -34,10 +34,3 @@ export const Nested = (args) => ( ); Nested.args = { onClick: action('clicked', { depth: 1 }) }; -Nested.parameters = { - docs: { - source: { - includeDecorators: false, - }, - }, -}; \ No newline at end of file diff --git a/lib/addons/src/types.ts b/lib/addons/src/types.ts index 73fdd0563abc..dc1627b0f849 100644 --- a/lib/addons/src/types.ts +++ b/lib/addons/src/types.ts @@ -62,7 +62,7 @@ export type StoryContext = StoryIdentifier & { globals: Args; hooks?: HooksContext; viewMode?: ViewMode; - originalStoryFn: ArgsStoryFn; + originalStoryFn?: ArgsStoryFn; }; export interface WrapperSettings {