diff --git a/code/ui/blocks/src/blocks/ArgTypes.stories.tsx b/code/ui/blocks/src/blocks/ArgTypes.stories.tsx index 5176d59621bb..a177868ba92a 100644 --- a/code/ui/blocks/src/blocks/ArgTypes.stories.tsx +++ b/code/ui/blocks/src/blocks/ArgTypes.stories.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { ArgTypes } from './ArgTypes'; @@ -35,6 +36,16 @@ export const OfStory: Story = { }, }; +export const OfUndefined: Story = { + args: { + // @ts-expect-error this is supposed to be undefined + // eslint-disable-next-line import/namespace + of: ExampleStories.NotDefined, + }, + parameters: { chromatic: { disableSnapshot: true } }, + decorators: [(s) => (window?.navigator.userAgent.match(/StorybookTestRunner/) ?
: s())], +}; + // NOTE: this will throw with no of prop export const OfStoryUnattached: Story = { parameters: { attached: false }, diff --git a/code/ui/blocks/src/blocks/ArgTypes.tsx b/code/ui/blocks/src/blocks/ArgTypes.tsx index 009d66cd8198..3515af129bbc 100644 --- a/code/ui/blocks/src/blocks/ArgTypes.tsx +++ b/code/ui/blocks/src/blocks/ArgTypes.tsx @@ -60,6 +60,9 @@ function getArgTypesFromResolved(resolved: ReturnType, props: ArgT export const ArgTypes: FC = (props) => { const { of } = props; + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } const resolved = useOf(of || 'meta'); const { argTypes, parameters } = getArgTypesFromResolved(resolved, props); const argTypesParameters = parameters.docs?.argTypes || ({} as ArgTypesParameters); diff --git a/code/ui/blocks/src/blocks/ArgsTable.tsx b/code/ui/blocks/src/blocks/ArgsTable.tsx index 378610a8a40b..8322254e8791 100644 --- a/code/ui/blocks/src/blocks/ArgsTable.tsx +++ b/code/ui/blocks/src/blocks/ArgsTable.tsx @@ -226,6 +226,9 @@ export const ArgsTable: FC = (props) => { ({ parameters, component, subcomponents } = context.storyById()); } catch (err) { const { of } = props as OfProps; + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } ({ projectAnnotations: { parameters }, } = context.resolveOf(of, ['component'])); diff --git a/code/ui/blocks/src/blocks/Canvas.stories.tsx b/code/ui/blocks/src/blocks/Canvas.stories.tsx index 4a6d75b4ea86..4022cb110043 100644 --- a/code/ui/blocks/src/blocks/Canvas.stories.tsx +++ b/code/ui/blocks/src/blocks/Canvas.stories.tsx @@ -33,26 +33,36 @@ export default meta; type Story = StoryObj; -export const DefaultAttached: Story = { +export const OfAttached: Story = { args: { of: ButtonStories.Primary, }, }; -export const DefaultUnattached: Story = { +export const OfUnattached: Story = { args: { of: ButtonStories.Primary, }, parameters: { attached: false }, }; -export const DefaultError: Story = { +export const OfError: Story = { args: { of: ButtonStories.ErrorStory, }, }; -export const UndefinedOf: Story = {}; +export const DefaultAttached: Story = {}; + +export const OfUndefined: Story = { + args: { + // @ts-expect-error this is supposed to be undefined + // eslint-disable-next-line import/namespace + of: ButtonStories.NotDefined, + }, + parameters: { chromatic: { disableSnapshot: true } }, + decorators: [(s) => (window?.navigator.userAgent.match(/StorybookTestRunner/) ?
: s())], +}; export const PropWithToolbar: Story = { name: 'Prop withToolbar = true', diff --git a/code/ui/blocks/src/blocks/Canvas.tsx b/code/ui/blocks/src/blocks/Canvas.tsx index d354fe775ad3..2245629b438d 100644 --- a/code/ui/blocks/src/blocks/Canvas.tsx +++ b/code/ui/blocks/src/blocks/Canvas.tsx @@ -115,7 +115,10 @@ const useDeprecatedPreviewProps = ( const stories = useStories(storyIds, docsContext); const isLoading = stories.some((s) => !s); const sourceProps = useSourceProps( - mdxSource ? { code: decodeURI(mdxSource), of: props.of } : { ids: storyIds, of: props.of }, + { + ...(mdxSource ? { code: decodeURI(mdxSource) } : { ids: storyIds }), + ...(props.of && { of: props.of }), + }, docsContext, sourceContext ); @@ -155,6 +158,10 @@ export const Canvas: FC = (props) => { const docsContext = useContext(DocsContext); const sourceContext = useContext(SourceContext); const { children, of, source } = props; + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } + const { isLoading, previewProps } = useDeprecatedPreviewProps(props, docsContext, sourceContext); let story: PreparedStory; @@ -175,7 +182,7 @@ export const Canvas: FC = (props) => { } } try { - sourceProps = useSourceProps({ ...source, of }, docsContext, sourceContext); + sourceProps = useSourceProps({ ...source, ...(of && { of }) }, docsContext, sourceContext); } catch (error) { if (!children) { hookError = error; diff --git a/code/ui/blocks/src/blocks/Controls.stories.tsx b/code/ui/blocks/src/blocks/Controls.stories.tsx index d8da8fabb0bd..7bde517b7bfa 100644 --- a/code/ui/blocks/src/blocks/Controls.stories.tsx +++ b/code/ui/blocks/src/blocks/Controls.stories.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { Controls } from './Controls'; @@ -30,6 +31,16 @@ export const OfStoryUnattached: Story = { }, }; +export const OfUndefined: Story = { + args: { + // @ts-expect-error this is supposed to be undefined + // eslint-disable-next-line import/namespace + of: ExampleStories.NotDefined, + }, + parameters: { chromatic: { disableSnapshot: true } }, + decorators: [(s) => (window?.navigator.userAgent.match(/StorybookTestRunner/) ?
: s())], +}; + export const IncludeProp: Story = { args: { of: ExampleStories.NoParameters, diff --git a/code/ui/blocks/src/blocks/Controls.tsx b/code/ui/blocks/src/blocks/Controls.tsx index 8a70a4a29520..9712aeda130e 100644 --- a/code/ui/blocks/src/blocks/Controls.tsx +++ b/code/ui/blocks/src/blocks/Controls.tsx @@ -24,6 +24,10 @@ type ControlsProps = ControlsParameters & { export const Controls: FC = (props) => { const { of } = props; + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } + const context = useContext(DocsContext); const { story } = context.resolveOf(of || 'story', ['story']); const { parameters, argTypes } = story; diff --git a/code/ui/blocks/src/blocks/Description.stories.tsx b/code/ui/blocks/src/blocks/Description.stories.tsx index 0e940c37cf54..a8f6bac08fd5 100644 --- a/code/ui/blocks/src/blocks/Description.stories.tsx +++ b/code/ui/blocks/src/blocks/Description.stories.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { Description } from './Description'; import { Button as ButtonComponent } from '../examples/Button'; @@ -107,9 +108,22 @@ export const OfStoryAsStoryCommentAndParameter: Story = { }, parameters: { relativeCsfPaths: ['../examples/Button.stories'] }, }; -export const OfUndefinedAttached: Story = { +export const DefaultAttached: Story = { parameters: { relativeCsfPaths: ['../examples/Button.stories'], attached: true }, }; +export const OfUndefinedAttached: Story = { + args: { + // @ts-expect-error this is supposed to be undefined + // eslint-disable-next-line import/namespace + of: DefaultButtonStories.NotDefined, + }, + parameters: { + chromatic: { disableSnapshot: true }, + relativeCsfPaths: ['../examples/Button.stories'], + attached: true, + }, + decorators: [(s) => (window?.navigator.userAgent.match(/StorybookTestRunner/) ?
: s())], +}; export const OfStringComponentAttached: Story = { name: 'Of "component" Attached', args: { diff --git a/code/ui/blocks/src/blocks/Description.tsx b/code/ui/blocks/src/blocks/Description.tsx index 645a4d95f54c..a6cda58ca930 100644 --- a/code/ui/blocks/src/blocks/Description.tsx +++ b/code/ui/blocks/src/blocks/Description.tsx @@ -125,6 +125,10 @@ const getDescriptionFromDeprecatedProps = ( const DescriptionContainer: FC = (props) => { const { of, type, markdown: markdownProp, children } = props; + + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } const context = useContext(DocsContext); const resolvedOf = useOf(of || 'meta'); let markdown; diff --git a/code/ui/blocks/src/blocks/Source.stories.tsx b/code/ui/blocks/src/blocks/Source.stories.tsx index ad70eafedf80..ef0b85c3dce7 100644 --- a/code/ui/blocks/src/blocks/Source.stories.tsx +++ b/code/ui/blocks/src/blocks/Source.stories.tsx @@ -53,6 +53,16 @@ export const Of: Story = { }, }; +export const OfUndefined: Story = { + args: { + // @ts-expect-error this is supposed to be undefined + // eslint-disable-next-line import/namespace + of: ParametersStories.NotDefined, + }, + parameters: { chromatic: { disableSnapshot: true } }, + decorators: [(s) => (window?.navigator.userAgent.match(/StorybookTestRunner/) ?
: s())], +}; + export const OfTypeProp: Story = { args: { of: ParametersStories.NoParameters, diff --git a/code/ui/blocks/src/blocks/Source.tsx b/code/ui/blocks/src/blocks/Source.tsx index 335c338dc611..5b43a4828537 100644 --- a/code/ui/blocks/src/blocks/Source.tsx +++ b/code/ui/blocks/src/blocks/Source.tsx @@ -126,8 +126,13 @@ export const useSourceProps = ( // The check didn't actually change the type. let stories: PreparedStory[] = storiesFromIds as PreparedStory[]; - if (props.of) { - const resolved = docsContext.resolveOf(props.of, ['story']); + const { of } = props; + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } + + if (of) { + const resolved = docsContext.resolveOf(of, ['story']); stories = [resolved.story]; } else if (stories.length === 0) { try { diff --git a/code/ui/blocks/src/blocks/Story.stories.tsx b/code/ui/blocks/src/blocks/Story.stories.tsx index 5f416e055724..dce6292a643c 100644 --- a/code/ui/blocks/src/blocks/Story.stories.tsx +++ b/code/ui/blocks/src/blocks/Story.stories.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { Story as StoryBlock } from './Story'; @@ -45,6 +46,16 @@ export const OfError: Story = { }, }; +export const OfUndefined: Story = { + args: { + // @ts-expect-error this is supposed to be undefined + // eslint-disable-next-line import/namespace + of: ButtonStories.NotDefined, + }, + parameters: { chromatic: { disableSnapshot: true } }, + decorators: [(s) => (window?.navigator.userAgent.match(/StorybookTestRunner/) ?
: s())], +}; + export const Inline: Story = { args: { of: StoryParametersStories.NoParameters, diff --git a/code/ui/blocks/src/blocks/Story.tsx b/code/ui/blocks/src/blocks/Story.tsx index 42d84ff90947..42f7e5935ae3 100644 --- a/code/ui/blocks/src/blocks/Story.tsx +++ b/code/ui/blocks/src/blocks/Story.tsx @@ -89,6 +89,10 @@ export type StoryProps = (StoryDefProps | StoryRefProps) & StoryParameters; export const getStoryId = (props: StoryProps, context: DocsContextProps): StoryId => { const { id, of, meta, story } = props as StoryRefProps; + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } + if (id) { deprecate(dedent`Referencing stories by \`id\` is deprecated, please use \`of\` instead.