Storybook CSF 3.0 标题体系详解:meta.title、component 自动标题与 story.name 的命名规则
【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook
这篇技术指南聚焦 Storybook Component Story Format 3.0(CSF 3.0)中的"标题(title)与命名"控制机制,内容以仓库中面向组件命名示例的代码片段文档为主体,并结合其出处——Sidebar & URLS 配置文档中的 "CSF 3.0 auto-titles" 章节展开。读完本文,你将掌握如何在 CSF 文件中通过title、component、name精确控制组件与单个 Story 在侧边栏层级与 URL 中的呈现,理解 Storybook 自动推导标题(auto-title)的完整规则,并能在 JS/TS/MDX 三种场景中正确写出可运行的标题配置。
一、标题机制一览:title、component 与 name 三者各自负责什么
在 CSF 3.0 中,每个.stories文件通过meta(默认导出)描述组件容器,通过命名导出对象描述单个 Story。决定"这个组件/这条 Story 在 Storybook 里叫什么、出现在侧边栏哪个位置"的核心字段有三个:
| 字段 | 作用层级 | 用途 |
|---|---|---|
title | meta(文件级) | 设置 Story 容器在侧边栏中的完整路径名,含/时会产生分组层级,例如components/Button |
component | meta(文件级) | 关联被测组件;当未设置title时,Storybook 会根据文件物理路径自动推断标题 |
name | 单个 Story | 覆盖该 Story 的显示名称;不设置时默认使用导出变量名 |
三者可同时使用并相互配合,这也是示例文档要表达的核心:自动标题(auto-title)与显式标题选项完全兼容,设置title后你依然可以使用显式的name逐条命名 Story。
二、CSF 3.0 meta 的标准写法:JS 与 TS 双版本
以按钮组件为例,示例文档给出了.js/.jsx与.ts/.tsx两种等价写法。
JS/JSX 版本(对应 src/components/Button/Button.stories.js):
import { Button } from './Button'; export default { // Sets the name for the stories container title: 'components/Button', // The component name will be used if `title` is not set component: Button, }; // The story variable name will be used if `name` is not set const Primary = { // Sets the name for that particular story name: 'Primary', args: { label: 'Button', }, };TypeScript 版本使用satisfies Meta<typeof Button>做类型收窄,让框架在编译期帮你校验 title/component/args 等字段拼写:
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc. import type { Meta, StoryObj } from '@storybook/your-framework'; import { Button } from './Button'; const meta = { // Sets the name for the stories container title: 'components/Button', // The component name will be used if `title` is not set component: Button, } satisfies Meta<typeof Button>; export default meta; type Story = StoryObj<typeof meta>; // The story variable name will be used if `name` is not set const Primary: Story = { // Sets the name for that particular story name: 'Primary', args: { label: 'Button', }, };两点实践提醒(对应示例中的注释):
- 类型导入处的
@storybook/your-framework是占位符,应按实际框架替换,例如@storybook/react-vite、@storybook/nextjs、@storybook/vue3-vite等。 title是可选的:一旦省略,Storybook 会根据文件所在位置自动推断标题,而component字段仍用于类型推断与文档生成,因此建议始终显式写出。
注意:示例中的对象式Primary是尚未作为命名导出列出的写法;若想让 Story 出现在侧边栏,仍需通过export const Primary = { ... }之类的方式导出(CSF 3.0 中常见的是把对象拆出来,再export const X = { ...Primary })。从仓库中的 CSF 解析实现看,meta 中title的取值会被用于生成稳定 storyId 与 URL 中的kind,这正是 title 命名在全局唯一的根因,详见 get-story-id.ts。
三、title 的斜杠语法:如何构建侧边栏分组层级
示例把 title 写作components/Button,其中/是侧边栏的分组分隔符。Storybook 会按共同前缀把带斜杠的 title 归组:所有components/...标题下的组件会收进一个名为components的分组(文件夹),Button成为该分组下的叶子节点。
Sidebar & URLS 文档给出了两条实操建议:
- 顶层节点默认被渲染为 "Roots"(侧边栏的"区段"),更低层分组显示为文件夹;如想将顶层节点也折叠成文件夹,可在
./storybook/manager.js中将sidebar.showRoots设为false。 - 推荐的层级命名尽量镜像组件文件的文件系统路径:例如组件在
components/modals/Alert.js,那么 Stories 文件命名为components/modals/Alert.stories.js,title 写为Components/Modals/Alert,让目录结构、文件名与侧边栏结构一一对应,便于长期维护。
四、省略 title:Storybook 的自动标题(auto-title)规则
自 Storybook 6.4 引入 CSF 3.0(实验性)起,你可以省略 meta 中的title,让 Storybook 依据故事文件的物理位置自动推断标题,这正是示例文档出现的上下文。自动标题与title、name等显式配置可以并存、按需混用。
自动标题的推断逻辑实现在 autoTitle.ts 中,核心函数userOrAutoTitleFromSpecifier的优先级是:匹配到 stories 配置项后,若存在用户显式title,优先用用户 title;仅在缺失时才由文件路径推导。该文件还实现了若干重要启发式规则,可由对应测试 autoTitle.test.ts 印证:
- 保留大小写(Storybook 6.5 起):不再依赖 Lodash
startCase转换,components/MyComponent文件会得到components/MyComponent(而不是被拆词成My Component),文件名大小写被原样保留。 - 去除冗余文件名:当文件名与父目录同名(如
MyComponent/MyComponent.stories.ts),或文件名为index.stories.ts时,重复段会被剔除——按旧行为Components/MyComponent/MyComponent会简化为Components/MyComponent。相关示例见 storybook-csf-3-auto-title-redundant.md。若需要保留旧命名,只需显式给 meta 添加title。 - 剥离后缀与扩展名:推导时会去掉
.story(s)、文件扩展名以及路径中的分隔冗余(sanitize函数与pathJoin实现)。 - titlePrefix 自动前缀:若在 stories 配置对象中配置了
titlePrefix,所有匹配故事(无论自动还是显式 title)都会加上此前缀;测试中的快照如atoms/title与atoms/...直接证明了显式 title 与前缀的拼接行为。
需要说明的是,自动标题会保留文件系统路径的层级作为侧边栏层级。例如当你的.storybook/main.ts用stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)']加载 stories 且文件位于src/components/Button.stories.tsx时,该组件在侧边栏会自动显示为components/Button(示例文档语境下的components/My Component情形同理)。
五、story 的 name 与导出变量名:谁决定显示名
示例中PrimaryStory 同时设置了export const变量名与name: 'Primary'。二者的分工在 Sidebar & URLS 文档中被明确表述:
Storybook will prioritize the
idover the title for ID generation if provided and prioritize thestory.nameover the export key for display.
即:侧边栏与 Docs 中的显示名以story.name为准,未设置时才退化为导出变量名。因此当你要把导出变量名留作代码内引用、却想让读者看到更友好的标题时(例如含空格、中文或长描述),就给 Story 设置name。相应地,story 显示名的修改会自动参与 URL 与 permalink 的生成。
六、从 title 到 URL:storyId 的生成规则
title 不只影响观感,还会决定每个 Story 的稳定 ID 与可分享 URL。默认规则是:Storybook 依据"组件 title + 故事名"生成 ID;例如 title 为foo/bar、导出名为baz的故事会得到 IDfoo-bar--baz,对应链接形如?path=/story/foo-bar--baz(见 Sidebar & URLS 文档)。
若需要在不破坏既有 permalink 的前提下调整层级或显示名,可手动为 meta/Story 提供稳定的id(id优先级高于 title),这在发布型 Storybook 中尤其重要。整体调用链在仓库中可见于 get-story-id.ts:先通过getStoryTitle拿到(自动或用户)title,再由storyNameFromExport归一化故事名,最终toId(autoTitle, storyName)产出 storyId,title 经sanitize归一化为 URL 友好的kind。
七、MDX 文档页里的 Meta/Story:文档页标题与组件页引用
在.mdx文档文件中,同样使用标题体系组织页面。示例文档给出了Button.mdx的用法(注意其中的 import 写法为示例使用方式,来自 '@storybook/addon-docs/blocks'):
import { Meta, Story } from '@storybook/addon-docs/blocks'; {/* 👇 Documentation-only page */} <Meta title="Documentation" /> {/* 👇 Component documentation page */} import * as ButtonStories from './Button.stories'; <Meta of={ButtonStories} /> <Story of={ButtonStories.Primary} />该示例同时展示三种常见形态:
- 纯文档页(documentation-only page):通过
<Meta title="Documentation" />显式命名一个不含组件渲染的文档页面,title 决定其在侧边栏中的层级归属。 - 组件文档页:
<Meta of={ButtonStories} />引用同目录下Button.stories模块的全部导出,让该 MDX 页与 CSF 中定义的组件及标题自动关联。 - 渲染指定故事:
<Story of={ButtonStories.Primary} />基于of语法按引用渲染Primary这条 Story,无需手动复制 args 配置。
由此可以总结出贯穿 JS/TS/MDX 的统一心智模型:CSF 文件是"单一事实来源",title/自动标题决定容器归属,name/导出名决定故事显示名,Meta/Story的of引用则让文档页复用这套命名体系,从而保持侧边栏、URL、文档三处命名一致。
八、小结:何时显式 title,何时交给自动标题
- 侧边栏需要精确层级、需按业务模块而非目录组织、或目录路径与展示名不一致时,在 meta 中显式声明
title(配合/分隔),这是最可控的方案; - 目录结构合理、希望"移动文件即自动重命名"时,省略
title,依赖文件路径自动推断,并用titlePrefix统一打前缀; - 无论哪种方案,都可以给单条 Story 设置
name控制显示名,并牢记只有显式title缺失时自动推断才会生效,component字段与命名无关却对类型安全与文档自动生成至关重要。
上述所有规则,均可回到仓库中的示例片段、侧边栏配置文档以及 autoTitle.ts、get-story-id.ts 及其测试处进一步验证,是理解 Storybook 命名与路由体系的可靠参考入口。
【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考