Skip to content

Commit 8d9d279

Browse files
Merge pull request #20810 from sheriffMoose/docs/makeTitle
docs: improve storyIndexers & makeTitle documentation
2 parents 7b835cd + 3d4687d commit 8d9d279

File tree

6 files changed

+88
-63
lines changed

6 files changed

+88
-63
lines changed

docs/configure/sidebar-and-urls.md

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -137,52 +137,55 @@ When Storybook generates the titles for all matching stories, they'll retain the
137137

138138
### Story Indexers
139139

140-
Story Indexers are usually responsible of crawling through your filesystem on your given glob path, and retrieve the stories that match that glob, afterwards Storybook analyzes these stories and create entries for these stories in the `index.json` (formerly `stories.json`). This `index.json` is used to populate the sidebar links based on the `title` retrieved for each story from the story file.
141-
142-
For CSF, it is either auto generated or retrieved from the meta configuration.
140+
Story Indexers are a set of heuristics used by Storybook to crawl your filesystem based on a given glob pattern searching for matching stories, which is then used to generate an index.json (formerly stories.json) file responsible for populating the sidebar with the necessary information. By default, this heuristic will look for files that contain the following scheme \*.stories.@(js|jsx|ts|tsx). However, if you need, you can create your custom story indexer that you can use to include stories that have a different naming convention. For example:
143141

144142
<!-- prettier-ignore-start -->
145143

146144
<CodeSnippets
147145
paths={[
148-
'common/csf-3-example-title.ts.mdx',
146+
'common/storybook-main-csf-indexer.ts.mdx',
149147
]}
150148
/>
151149

152150
<!-- prettier-ignore-end -->
153151

154-
While for "Docs Only" pages, that title resides in the `title` attribute of the `Meta` tag. If the `title` attribute does not exist, Storybook indexer will be looking for the `of` attribute to retrieve a CSF story and get the title from there.
152+
### Processing custom titles
153+
154+
Out of the box, Storybook automatically infers the story's title based on a set of patterns, including, for example, the file's physical location. If you're working on creating a custom story indexer and you want to handle the titles based on your set of rules, you can adjust it and provide a `makeTitle` function inside the `loadCsf` function. Below is a condensed table and examples of how these patterns work and how they relate to stories.
155+
156+
| Pattern | Description |
157+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
158+
| `titlePrefix` | Prefixes the indexed story title based on the [configuration](./overview.md#with-a-configuration-object). |
159+
| `title` | Requires CSF and MDX.<br/>Infers the story title based on the information defined in the metadata. |
160+
| `name` | Requires CSF and MDX.<br/> Overrides the story title based on the provided [name](../writing-stories/introduction.md#rename-stories) property. |
161+
| `component` | Requires CSF.<br/> Generates the title based on the component property defined in the metadata. |
162+
| `of` | Requires MDX.<br/> Retrieves the title based on the referenced story file. |
163+
| `story export` | Requires CSF. <br/> Defines the title based on the [named story export](../api/csf.md#named-story-exports). |
164+
| `filename` | Enabled with custom indexers.<br/> Defines the story title based on the filename parsed with the indexer. |
155165

156166
<!-- prettier-ignore-start -->
157167

158168
<CodeSnippets
159169
paths={[
160-
'common/storybook-auto-docs-mdx-docs-docs-only-page.mdx.mdx',
170+
'common/csf-3-example-title.ts.mdx',
171+
'common/csf-3-example-title.mdx.mdx',
161172
]}
162173
/>
163174

164175
<!-- prettier-ignore-end -->
165176

166-
Typically Storybook provides indexing capabilities for files that end with `.(story|stories).@(js|ts|jsx|tsx|mdx)`. If you feel the need to include stories that have different naming convention, e.g. [`20478`](https://github.com/storybookjs/storybook/issues/20478), you will need to introduce a new story indexer.
167-
168177
<!-- prettier-ignore-start -->
169178

170179
<CodeSnippets
171180
paths={[
172-
'common/storybook-main-csf-indexer.js.mdx',
181+
'common/storybook-main-story-indexer-main.ts.mdx'
173182
]}
174183
/>
175184

176185
<!-- prettier-ignore-end -->
177186

178-
Another example listed below for indexing `.md` & `.html` files which is already implemented by one of our community addons [`Markdown Docs`](https://storybook.js.org/addons/@sheriffmoose/storybook-md/).
187+
<div class="aside">
179188

180-
<!-- prettier-ignore-start -->
189+
💡 Story indexers are a great way to get non-developers playing with your components and stories. They can do much more than documented here; we encourage you to check out the [`@storybook-extras/markdown` ](https://storybook.js.org/addons/@storybook-extras/markdown/) to learn more about these techniques.
181190

182-
<CodeSnippets
183-
paths={[
184-
'common/storybook-main-md-html-indexer.js.mdx',
185-
]}
186-
/>
187-
188-
<!-- prettier-ignore-end -->
191+
</div>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
```mdx
2+
{/* src/components/Button/Button.mdx */}
3+
4+
import { Meta } from '@storybook/blocks';
5+
6+
{/* 👇 Documentation-only page */}
7+
<Meta title="Documentation" />
8+
9+
10+
{/* 👇 Component documentation page */}
11+
import * as ExampleComponentStories from './ExampleComponent.stories';
12+
13+
<Meta of={ExampleComponentStories} />
14+
```
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
```ts
2-
// CSF 3
2+
// src/components/Button/Button.stories.tsx
3+
34
const meta: Meta<Button> = {
5+
// Sets the name for the stories container
46
title: 'components/Button',
7+
// The component name will be used if `title` is not set
58
component: Button,
69
};
710
export default meta;
11+
12+
// The story variable name will be used if `name` is not set
13+
const Primary: Story = {
14+
// Sets the name for that particular story
15+
name: 'Primary',
16+
args: {
17+
label: 'Button',
18+
},
19+
};
820
```

docs/snippets/common/storybook-main-csf-indexer.js.mdx renamed to docs/snippets/common/storybook-main-csf-indexer.ts.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
```js
2-
// .storybook/main.js
1+
```ts
2+
// .storybook/main.ts
33

44
import { readFileSync } from 'fs';
55
import { loadCsf } from '@storybook/csf-tools';
@@ -16,8 +16,8 @@ export default {
1616
test: /(stories|story)\.[tj]sx?$/,
1717
indexer,
1818
},
19-
...(indexers || [])
20-
]
21-
}
19+
...(indexers || []),
20+
];
21+
},
2222
};
2323
```

docs/snippets/common/storybook-main-md-html-indexer.js.mdx

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
```ts
2+
// .storybook/main.ts
3+
4+
// Replace your-framework with the framework you are using (e.g., angular, react-webpack5, vue3-webpack5)
5+
import type { StorybookConfig } from '@storybook/your-framework';
6+
7+
// this can be as easy as fs.readFileSync and return the string
8+
// or as complex as creating a new MDX file with the content of the original file
9+
import { parseCode } from './parseCode';
10+
11+
const config: StorybookConfig = {
12+
storyIndexers: (indexers, addonOptions) => {
13+
const indexer = async (fileName, compilationOptions) => {
14+
const code = parseCode(fileName, addonOptions);
15+
const makeTitle = (userTitle) => {
16+
// Do something with the auto title retrieved by Storybook
17+
return userTitle;
18+
};
19+
20+
// Parse the CSF file with makeTitle as a custom context
21+
return loadCsf(code, { ...compilationOptions, makeTitle, fileName }).parse();
22+
};
23+
24+
return [
25+
{
26+
test: /\.(md|html)$/,
27+
indexer,
28+
},
29+
...(indexers || []),
30+
];
31+
},
32+
};
33+
34+
export default config;
35+
```

0 commit comments

Comments
 (0)