diff --git a/docs/configure/sidebar-and-urls.md b/docs/configure/sidebar-and-urls.md index f49f7a3c66ba..1e301206e38f 100644 --- a/docs/configure/sidebar-and-urls.md +++ b/docs/configure/sidebar-and-urls.md @@ -2,11 +2,11 @@ title: 'Sidebar & URLS' --- -Storybook’s sidebar lists all your stories grouped by component. When you have many components, you may also wish to group those components. To do so, you can add the `/` separator to the `title` of your CSF file and Storybook will group the stories into groups based on common prefixes: +Storybook’s sidebar lists all your stories grouped by component. When you have many components, you may also wish to group those components. To do so, you can add the `/` separator to the `title` of your CSF file, and Storybook will group the stories into groups based on common prefixes: ![Storybook sidebar anatomy](./sidebar-anatomy.jpg) -We recommend using a nesting scheme that mirrors the filesystem path of the components. For example, if you have a file `components/modals/Alert.js` name the CSF file `components/modals/Alert.stories.js` and title it `Components/Modals/Alert`. +We recommend using a nesting scheme that mirrors the filesystem path of the components. For example, if you have a file `components/modals/Alert.js`, name the CSF file `components/modals/Alert.stories.js` and title it `Components/Modals/Alert`. ## Roots @@ -26,76 +26,100 @@ If you’d prefer to show top-level nodes as folders rather than roots, you can -## Automatically generate titles +## Permalink to stories -With CSF 3.0 files, you can choose to leave out a title and let it be inferred from the story's path on disk instead: +By default, Storybook generates an `id` for each story based on the component title and the story name. This `id` in particular is used in the URL for each story, and that URL can serve as a permalink (primarily when you [publish](../sharing/publish-storybook.md) your Storybook). + +Consider the following story: -This is controlled by the way your stories are configured: +Storybook's ID-generation logic will give this the `id` `foo-bar--baz`, so the link would be `?path=/story/foo-bar--baz`. + +It is possible to manually set the story's id, which is helpful if you want to rename stories without breaking permalinks. Suppose you want to change the position in the hierarchy to `OtherFoo/Bar` and the story name to `Moo`. Here's how to do that: -Given this configuration, the stories file `../src/components/MyComponent.stories.tsx` will get the title `components/MyComponent`. +Storybook will prioritize the `id` over the title for ID generation if provided and prioritize the `story.name` over the export key for display. -You can further customize the generated title by modifying the stories configuration. +## CSF 3.0 auto-titles + +Storybook 6.4 introduced [CSF 3.0](https://storybook.js.org/blog/component-story-format-3-0/) as an experimental feature, allowing you to write stories more compactly. Suppose you're already using this format to write your stories. In that case, you can omit the `title` element from the default export and allow Storybook automatically infer it based on the file's physical location. For example, given the following configuration and story: -This configuration would match a custom file pattern, and add a custom prefix of Foo to each generated title. +When Storybook loads, the story can show up in the sidebar as `components/My Component`. -## Permalinking to stories +### Auto-title filename case -By default, Storybook generates an `id` for each story based on the component title and the story name. This `id` in particular is used in the URL for each story, and that URL can serve as a permalink (primarily when you [publish](../sharing/publish-storybook.md) your Storybook). +Starting with Storybook 6.5, story titles generated automatically no longer rely on Lodash's [startCase](https://lodash.com/docs/#startCase). +Instead, the file name casing is preserved, allowing additional control over the story title. For example, `components/My Component` will be defined as `components/MyComponent`. -Consider the following story: +If you need, you can revert to the previous pattern by adding the following configuration: -Storybook's ID-generation logic will give this the `id` `foo-bar--baz`, so the link would be `?path=/story/foo-bar--baz`. +### Auto-title redundant filenames + +In addition to improvements to the story file name casing, a new heuristic was introduced, removing redundant names in case the filename has the same name as the directory name, or if it's called `index.stories.js|ts`. For example, before `components/MyComponent/MyComponent.stories.js` was defined as `Components/MyComponent/MyComponent` in the sidebar. Now it will be defined as `Components/MyComponent`. -It is possible to manually set the id of a story, which is helpful if you want to rename stories without breaking permalinks. Suppose you want to change the position in the hierarchy to `OtherFoo/Bar` and the story name to `Moo`. Here's how to do that: +If you need to preserve the naming scheme, you can add the `title` element to the default export. For example: + + + +### Auto-title prefixes + +Additionally, if you customize your Storybook to load your stories based on a [configuration object](./overview.md#with-a-configuration-object), including a `titlePrefix`, Storybook automatically prefixes all titles to matching stories. For example, assuming you have the following configuration: + + + + -Storybook will prioritize the `id` over the title for ID generation if provided and prioritize the `story.name` over the export key for display. \ No newline at end of file +When Storybook generates the titles for all matching stories, they'll retain the `Custom` prefix. diff --git a/docs/snippets/common/component-story-auto-title.csf3-story.js.mdx b/docs/snippets/common/component-story-auto-title.csf3-story.js.mdx new file mode 100644 index 000000000000..74c50e85077b --- /dev/null +++ b/docs/snippets/common/component-story-auto-title.csf3-story.js.mdx @@ -0,0 +1,16 @@ +```js +// src/components/MyComponent.stories.js|jsx + +import { MyComponent } from './MyComponent'; + +/** + * Story written in CSF 3.0 with auto title generation + * See https://storybook.js.org/docs/7.0/react/api/csf + * to learn more about it. + */ +export default { component: MyComponent }; + +export const Default = { + args: { message: 'Hello world!' }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/common/component-story-auto-title.js.mdx b/docs/snippets/common/component-story-auto-title.js.mdx deleted file mode 100644 index 33b7a49872bc..000000000000 --- a/docs/snippets/common/component-story-auto-title.js.mdx +++ /dev/null @@ -1,4 +0,0 @@ -```js -// CSF 3.0 - MyComponent.stories.js|jsx|ts|tsx -export default { component: MyComponent } -``` \ No newline at end of file diff --git a/docs/snippets/common/component-story-configuration.js.mdx b/docs/snippets/common/component-story-configuration.js.mdx deleted file mode 100644 index 05df51e2c8a5..000000000000 --- a/docs/snippets/common/component-story-configuration.js.mdx +++ /dev/null @@ -1,6 +0,0 @@ -```js -// ./storybook/main.js -module.exports = { - stories: ['../src'] -}; -``` \ No newline at end of file diff --git a/docs/snippets/common/storybook-csf-3-auto-title-redundant.js.mdx b/docs/snippets/common/storybook-csf-3-auto-title-redundant.js.mdx new file mode 100644 index 000000000000..26c9d0997b57 --- /dev/null +++ b/docs/snippets/common/storybook-csf-3-auto-title-redundant.js.mdx @@ -0,0 +1,17 @@ +```js +// components/MyComponent/MyComponent.stories.js|jsx|ts|tsx + +import { MyComponent } from './MyComponent.js' + +export default { + component: MyComponent, + title: 'components/MyComponent/MyComponent', +}; + +export const Default = { + args: { + something: 'Something else', + }, +}; + +``` \ No newline at end of file diff --git a/docs/snippets/common/storybook-main-auto-title-custom.js.mdx b/docs/snippets/common/storybook-main-auto-title-custom.js.mdx new file mode 100644 index 000000000000..96b6e0408971 --- /dev/null +++ b/docs/snippets/common/storybook-main-auto-title-custom.js.mdx @@ -0,0 +1,15 @@ +```js +// .storybook/main.js + +module.exports = { + stories: [{ directory: '../src', titlePrefix: 'Custom' }], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + core: { + builder: 'webpack5', + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/common/storybook-main-configuration-src-dir.main-js.js.mdx b/docs/snippets/common/storybook-main-configuration-src-dir.main-js.js.mdx new file mode 100644 index 000000000000..f7933dbf6e67 --- /dev/null +++ b/docs/snippets/common/storybook-main-configuration-src-dir.main-js.js.mdx @@ -0,0 +1,15 @@ +```js +// ./storybook/main.js + +module.exports = { + stories: ['../src'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + core: { + builder: 'webpack5' + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/common/storybook-manager-render-label-stories.js.mdx b/docs/snippets/common/storybook-manager-render-label-stories.js.mdx new file mode 100644 index 000000000000..a40abfbadc97 --- /dev/null +++ b/docs/snippets/common/storybook-manager-render-label-stories.js.mdx @@ -0,0 +1,13 @@ +```js +// .storybook/manager.js + +import { addons } from '@storybook/addons'; + +import startCase from 'lodash/startCase'; + +addons.setConfig({ + sidebar: { + renderLabel: ({ name, type }) => (type === 'story' ? name : startCase(name)), + }, +}); +``` \ No newline at end of file