diff --git a/MIGRATION.md b/MIGRATION.md index 6e48d1e75a4d..7db3b2fab2ff 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -19,6 +19,7 @@ - [Removed renderCurrentStory event](#removed-rendercurrentstory-event) - [Removed hierarchy separators](#removed-hierarchy-separators) - [Client API changes](#client-api-changes) + - [Removed support for duplicate kinds](#removed-support-for-duplicate-kinds) - [Removed Legacy Story APIs](#removed-legacy-story-apis) - [Can no longer add decorators/parameters after stories](#can-no-longer-add-decoratorsparameters-after-stories) - [Changed Parameter Handling](#changed-parameter-handling) @@ -414,6 +415,29 @@ addons.setConfig({ ### Client API changes +#### Removed support for duplicate kinds + +In 6.0 we removed the ability to split a kind's (component's) stories into multiple files because it was causing issues in hot module reloading (HMR). + +If you had N stories that contained `export default { title: 'foo/bar' }` (or the MDX equivalent ``), Storybook will now throw the error `Duplicate title '${kindName}' used in multiple files`. + +To split a component's stories into multiple files, e.g. for the `foo/bar` example above: + +- Create a single file with the `export default { title: 'foo/bar' }` export, which is the primary file +- Comment out or delete the default export from the other files +- Re-export the stories from the other files in the primary file + +So the primary example might look like: + +```js +export default { title: 'foo/bar' }; +export * from './Bar1.stories' +export * from './Bar2.stories' +export * from './Bar3.stories' + +export const SomeStory = () => ...; +``` + #### Removed Legacy Story APIs In 6.0 we removed a set of APIs from the underlying `StoryStore` (which wasn't publicly accessible): diff --git a/addons/docs/docs/recipes.md b/addons/docs/docs/recipes.md index 5ee6a4ee1c5d..21525c081e7a 100644 --- a/addons/docs/docs/recipes.md +++ b/addons/docs/docs/recipes.md @@ -44,11 +44,12 @@ Perhaps you want to write your stories in CSF, but document them in MDX? Here's import React from 'react'; import { Button } from './Button'; -export default { - title: 'Demo/Button', - component: Button, - includeStories: [], // or don't load this file at all -}; +// NOTE: no default export since `Button.stories.mdx` is the story file for `Button` now +// +// export default { +// title: 'Demo/Button', +// component: Button, +// }; export const basic = () => ; basic.parameters = { @@ -60,7 +61,7 @@ basic.parameters = { ```md import { Meta, Story } from '@storybook/addon-docs/blocks'; -import \* as stories from './Button.stories.js'; +import * as stories from './Button.stories.js'; import { SomeComponent } from 'path/to/SomeComponent'; diff --git a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js index 5ecfbc6b342c..a5dab9fb2b7d 100644 --- a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js +++ b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js @@ -1,10 +1,12 @@ import React from 'react'; import { Button } from '@storybook/react/demo'; -export default { - title: 'Addons/Docs/csf-with-mdx-docs', - component: Button, - includeStories: [], // or don't load this file at all -}; +// NOTE: commented out default since these stories are re-exported +// in the primary file './csf-docs-with-mdx-docs.stories.mdx' +// +// export default { +// title: 'Addons/Docs/csf-with-mdx-docs', +// component: Button, +// }; export const basic = () => ; diff --git a/lib/core/src/client/preview/loadCsf.ts b/lib/core/src/client/preview/loadCsf.ts index ee982cdb907f..7c308d7aab4f 100644 --- a/lib/core/src/client/preview/loadCsf.ts +++ b/lib/core/src/client/preview/loadCsf.ts @@ -22,6 +22,9 @@ const loadStories = ( framework: string, { clientApi, storyStore }: { clientApi: ClientApi; storyStore: StoryStore } ) => () => { + // Make sure we don't try to define a kind more than once within the same load + const loadedKinds = new Set(); + let reqs = null; // todo discuss / improve type check if (Array.isArray(loadable)) { @@ -106,6 +109,18 @@ const loadStories = ( args: kindArgs, argTypes: kindArgTypes, } = meta; + + if (loadedKinds.has(kindName)) { + throw new Error( + dedent` + Duplicate title '${kindName}' used in multiple files; use unique titles or a primary file for '${kindName}' with re-exported stories. + + https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#removed-support-for-duplicate-kinds + ` + ); + } + loadedKinds.add(kindName); + // We pass true here to avoid the warning about HMR. It's cool clientApi, we got this // todo discuss: TS now wants a NodeModule; should we fix this differently? const kind = clientApi.storiesOf(kindName, true as any);