From cb70145e70cc075acd07f89e4f7253ff619fac67 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Jul 2022 12:32:37 +1000 Subject: [PATCH] Add some template exampes to external docs And make sure doc blocks use the "primary" story by id when possible. --- examples/external-docs/.storybook/main.cjs | 2 ++ .../external-docs/components/Template.mdx | 8 +++++ examples/external-docs/components/button.mdx | 7 +++++ .../external-docs/components/emoji-button.mdx | 7 +++++ examples/external-docs/pages/button.mdx | 1 + examples/external-docs/pages/emoji-button.mdx | 1 + lib/blocks/src/blocks/ArgsTable.tsx | 30 ++++++------------- lib/blocks/src/blocks/Description.tsx | 4 +-- lib/blocks/src/blocks/Source.tsx | 7 +---- .../src/docs-context/DocsContext.ts | 18 +++++++++-- 10 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 examples/external-docs/components/Template.mdx create mode 100644 examples/external-docs/components/button.mdx create mode 100644 examples/external-docs/components/emoji-button.mdx create mode 120000 examples/external-docs/pages/button.mdx create mode 120000 examples/external-docs/pages/emoji-button.mdx diff --git a/examples/external-docs/.storybook/main.cjs b/examples/external-docs/.storybook/main.cjs index bd2a03f7012b..7cc9f3ab71e1 100644 --- a/examples/external-docs/.storybook/main.cjs +++ b/examples/external-docs/.storybook/main.cjs @@ -1,8 +1,10 @@ const config = { stories: [ + '../Introduction.mdx', { directory: '../components', titlePrefix: 'Demo', + files: '**/!(Template).(stories.tsx|mdx)', }, ], logLevel: 'debug', diff --git a/examples/external-docs/components/Template.mdx b/examples/external-docs/components/Template.mdx new file mode 100644 index 000000000000..fc2a3cf935cf --- /dev/null +++ b/examples/external-docs/components/Template.mdx @@ -0,0 +1,8 @@ +import { Title, Description, ArgsTable, Stories, PRIMARY_STORY } from '@storybook/addon-docs'; + +# This is a template! + + +<Description /> +<ArgsTable story={PRIMARY_STORY} /> +<Stories /> diff --git a/examples/external-docs/components/button.mdx b/examples/external-docs/components/button.mdx new file mode 100644 index 000000000000..8520aedaa309 --- /dev/null +++ b/examples/external-docs/components/button.mdx @@ -0,0 +1,7 @@ +import { Meta } from '@storybook/blocks'; +import * as ButtonStories from './button.stories.tsx'; +import Template from './Template.mdx'; + +<Meta of={ButtonStories} /> + +<Template /> diff --git a/examples/external-docs/components/emoji-button.mdx b/examples/external-docs/components/emoji-button.mdx new file mode 100644 index 000000000000..9aa0417cf745 --- /dev/null +++ b/examples/external-docs/components/emoji-button.mdx @@ -0,0 +1,7 @@ +import { Meta } from '@storybook/addon-docs'; +import * as EmojiButtonStories from './emoji-button.stories.tsx'; +import Template from './Template.mdx'; + +<Meta of={EmojiButtonStories} /> + +<Template /> diff --git a/examples/external-docs/pages/button.mdx b/examples/external-docs/pages/button.mdx new file mode 120000 index 000000000000..38304dea6d90 --- /dev/null +++ b/examples/external-docs/pages/button.mdx @@ -0,0 +1 @@ +../components/button.mdx \ No newline at end of file diff --git a/examples/external-docs/pages/emoji-button.mdx b/examples/external-docs/pages/emoji-button.mdx new file mode 120000 index 000000000000..65f6cb84e8f6 --- /dev/null +++ b/examples/external-docs/pages/emoji-button.mdx @@ -0,0 +1 @@ +../components/emoji-button.mdx \ No newline at end of file diff --git a/lib/blocks/src/blocks/ArgsTable.tsx b/lib/blocks/src/blocks/ArgsTable.tsx index d22d4d366dfd..23cb683040ad 100644 --- a/lib/blocks/src/blocks/ArgsTable.tsx +++ b/lib/blocks/src/blocks/ArgsTable.tsx @@ -41,20 +41,12 @@ type StoryProps = BaseProps & { type ArgsTableProps = BaseProps | OfProps | ComponentsProps | StoryProps; -const getContext = (storyId: string, context: DocsContextProps) => { - const story = context.storyById(storyId); - if (!story) { - throw new Error(`Unknown story: ${storyId}`); - } - return context.getStoryContext(story); -}; - const useArgs = ( storyId: string, context: DocsContextProps ): [Args, (args: Args) => void, (argNames?: string[]) => void] => { const channel = addons.getChannel(); - const storyContext = getContext(storyId, context); + const storyContext = context.getStoryContext(context.storyById()); const [args, setArgs] = useState(storyContext.args); useEffect(() => { @@ -79,7 +71,7 @@ const useArgs = ( const useGlobals = (storyId: string, context: DocsContextProps): [Globals] => { const channel = addons.getChannel(); - const storyContext = getContext(storyId, context); + const storyContext = context.getStoryContext(context.storyById()); const [globals, setGlobals] = useState(storyContext.globals); useEffect(() => { @@ -95,11 +87,11 @@ const useGlobals = (storyId: string, context: DocsContextProps): [Globals] => { export const extractComponentArgTypes = ( component: Component, - { id, storyById }: DocsContextProps, + context: DocsContextProps, include?: PropDescriptor, exclude?: PropDescriptor ): StrictArgTypes => { - const { parameters } = storyById(id); + const { parameters } = context.storyById(); const { extractArgTypes }: { extractArgTypes: ArgTypesExtractor } = parameters.docs || {}; if (!extractArgTypes) { throw new Error(ArgsTableError.ARGS_UNSUPPORTED); @@ -114,13 +106,10 @@ const isShortcut = (value?: string) => { return value && [CURRENT_SELECTION, PRIMARY_STORY].includes(value); }; -export const getComponent = ( - props: ArgsTableProps = {}, - { id, storyById }: DocsContextProps -): Component => { +export const getComponent = (props: ArgsTableProps = {}, context: DocsContextProps): Component => { const { of } = props as OfProps; const { story } = props as StoryProps; - const { component } = storyById(id); + const { component } = context.storyById(); if (isShortcut(of) || isShortcut(story)) { return component || null; } @@ -149,7 +138,7 @@ export const StoryTable: FC< StoryProps & { component: Component; subcomponents: Record<string, Component> } > = (props) => { const context = useContext(DocsContext); - const { id: currentId, componentStories } = context; + const { id: currentId } = context; const { story: storyName, component, @@ -167,7 +156,7 @@ export const StoryTable: FC< break; } case PRIMARY_STORY: { - const primaryStory = componentStories()[0]; + const primaryStory = context.storyById(); storyId = primaryStory.id; break; } @@ -228,11 +217,10 @@ export const ComponentsTable: FC<ComponentsProps> = (props) => { export const ArgsTable: FC<ArgsTableProps> = (props) => { const context = useContext(DocsContext); - const { id, storyById } = context; const { parameters: { controls }, subcomponents, - } = storyById(id); + } = context.storyById(); const { include, exclude, components, sort: sortProp } = props as ComponentsProps; const { story: storyName } = props as StoryProps; diff --git a/lib/blocks/src/blocks/Description.tsx b/lib/blocks/src/blocks/Description.tsx index 7d2b839ac3b4..80203c559b0d 100644 --- a/lib/blocks/src/blocks/Description.tsx +++ b/lib/blocks/src/blocks/Description.tsx @@ -32,9 +32,9 @@ const noDescription = (component?: Component): string | null => null; export const getDescriptionProps = ( { of, type, markdown, children }: DescriptionProps, - { id, storyById }: DocsContextProps<any> + { storyById }: DocsContextProps<any> ): PureDescriptionProps => { - const { component, parameters } = storyById(id); + const { component, parameters } = storyById(); if (children || markdown) { return { markdown: children || markdown }; } diff --git a/lib/blocks/src/blocks/Source.tsx b/lib/blocks/src/blocks/Source.tsx index c714ed6a33b9..e0cfe2037ef4 100644 --- a/lib/blocks/src/blocks/Source.tsx +++ b/lib/blocks/src/blocks/Source.tsx @@ -94,12 +94,7 @@ export const getSourceProps = ( sourceContext: SourceContextProps ): PureSourceProps & SourceStateProps => { const { id: currentId, storyById } = docsContext; - let parameters = {} as Parameters; - try { - ({ parameters } = storyById(currentId)); - } catch (err) { - // TODO: in external mode, there is no "current" - } + const { parameters } = storyById(); const codeProps = props as CodeProps; const singleProps = props as SingleSourceProps; diff --git a/lib/preview-web/src/docs-context/DocsContext.ts b/lib/preview-web/src/docs-context/DocsContext.ts index 5efbd74ab877..1f3035364458 100644 --- a/lib/preview-web/src/docs-context/DocsContext.ts +++ b/lib/preview-web/src/docs-context/DocsContext.ts @@ -18,6 +18,8 @@ export class DocsContext<TFramework extends AnyFramework> implements DocsContext private nameToStoryId: Map<StoryName, StoryId>; + private primaryStory?: Story<TFramework>; + constructor( public readonly id: StoryId, public readonly title: ComponentTitle, @@ -48,7 +50,9 @@ export class DocsContext<TFramework extends AnyFramework> implements DocsContext if (addToComponentStories) { this.nameToStoryId.set(annotation.name, annotation.id); - this.componentStoriesValue.push(this.storyById(annotation.id)); + const story = this.storyById(annotation.id); + this.componentStoriesValue.push(story); + if (!this.primaryStory) this.primaryStory = story; } }); } @@ -75,8 +79,16 @@ export class DocsContext<TFramework extends AnyFramework> implements DocsContext return this.componentStoriesValue; }; - storyById = (inputStoryId?: StoryId) => { - const storyId = inputStoryId || this.id; + storyById = (storyId?: StoryId) => { + if (!storyId) { + if (!this.primaryStory) + throw new Error( + `No primary story defined for docs entry. Did you forget to use \`<Meta>\`?` + ); + + return this.primaryStory; + } + const csfFile = this.storyIdToCSFFile.get(storyId); if (!csfFile) throw new Error(`Called \`storyById\` for story that was never loaded: ${storyId}`);