拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Storybook Story 分组指南:借助 title 的 `/` 分隔符构建可展开的组件层级(含 CSF 3 / CSF Next / Svelte CSF 多框架示例)

Storybook Story 分组指南借助 title 的/分隔符构建可展开的组件层级含 CSF 3 / CSF Next / Svelte CSF 多框架示例【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook本篇技术指南基于 Storybook 官方文档片段 docs/_snippets/button-story-grouped.md 展开。它讲解的是 Storybook 中最常见的侧边栏组织手法在 CSF 文件的meta或default export中把title写成Design System/Atoms/Button这种用/分隔的层级路径从而把多个相关组件归并到同一个可展开的分组里。读完本文你将掌握「显式分组标题」的全框架写法Angular、React、Vue、Svelte、Web Components并理解分组标题如何影响侧边栏的 Roots 展示、Story 的自动 id 生成与 URL 链接以及它与 CSF 3.0 自动标题auto-titles机制之间的取舍关系。在进入具体配置前先看该分组写法在侧边栏中的实际呈现效果。下图为 Button、Checkbox 两个组件在Design System/Atoms分组路径下的展示结果截图自 docs/_assets/writing-stories/naming-hierarchy-with-path.png该图与片段同属于 docs/writing-stories/naming-components-and-hierarchy.mdx 的 Grouping 一节为什么需要给 Story 分组先理解侧边栏的层级结构Storybook 的侧边栏会把所有 Story 按组件组织起来而当项目里的组件变多时原始平铺列表会让导航迅速失控。分组的意义就是让「哪些组件属于同一套设计系统 / 同一个业务模块」在 UI 上一目了然并且可以被折叠、被搜索、被按层级过滤。按 docs/writing-stories/naming-components-and-hierarchy.mdx 的说明一个使用了分组标题的 Storybook 层级通常由以下几层构成Category类别Storybook 为 Story 与文档页生成的最顶层分组Folder文件夹位于中间层级的组织单元用来把同一特性或同一业务区块的组件与 Story 归拢到一起在侧边栏里呈现为可展开的文件夹Component组件表示被该 Story 测试的具体组件Docs文档页Storybook 为组件自动生成的文档页面AutodocsStory测试组件某个具体状态的单个用例。上面截图里的DESIGN SYSTEM → Atoms → Button/Checkbox正是这套结构的一个缩影Design System是根级类别CategoryAtoms是可展开的文件夹FolderButton、Checkbox则是各自独立的组件Component。分组机制的核心在title中使用/作为分隔符给 Story 分组不需要任何额外配置。只要你在 CSF 的metaCSF 3或default exportCSF 2 兼容写法里把title值中的层级路径用/分隔Storybook 就会自动按公共前缀把组件归入同一个可展开的分组中。这就是 docs/_snippets/button-story-grouped.md 里所有变体共同展示的核心写法title: Design System/Atoms/Button,第一段Design System会成为侧边栏最顶层的根分组第二段Atoms成为可展开的中间文件夹最后一段Button是真正的组件节点。同理把另一个组件的title写成Design System/Atoms/Checkbox见 docs/_snippets/checkbox-story-grouped.md两个组件就会被归并到同一个Design System → Atoms分组之下形成上图所示的效果。这一机制同时是「显式标题」与「隐式标题」两条组织路径中的「显式」分支。正如 docs/writing-stories/naming-components-and-hierarchy.mdx 所述隐式方法依赖 Story 文件在磁盘上的物理路径自动生成标题显式方法则直接使用title来安放 Story。官方文档强烈建议采用一种「镜像文件系统路径」的命名约定——例如磁盘上有components/modals/Alert.js就把故事文件命名为components/modals/Alert.stories.js并将title写为Components/Modals/Alert详见 docs/configure/user-interface/sidebar-and-urls.mdx。这样无论在文件系统还是侧边栏里组件都能被快速定位。分组标题的全框架分步写法title本身的写法在所有渲染器中都是同一个字符串差异只在于不同框架/不同 CSF 形态下这个值被放到哪个对象里。以下是完整的分框架对照可直接复制到对应项目中使用。AngularButton.stories.tsAngular 项目使用来自storybook/angular的类型标注。CSF 3 采用const meta: MetaButtonexport default metaimport type { Meta } from storybook/angular; import { Button } from ./button.component; const meta: MetaButton { /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, }; export default meta;而 CSF Next试验性形态通过从../.storybook/preview导入的preview.meta({ ... })来构造metaimport preview from ../.storybook/preview; import { Button } from ./button.component; const meta preview.meta({ /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, });React通用 TS/JSX 写法对于 React、Vue 等「通用 CSF 3」渲染器官方片段使用satisfies Metatypeof Button保证类型安全并特别注明需要把storybook/your-framework替换成实际使用的框架包例如storybook/react-vite、storybook/nextjs、storybook/vue3-vite// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc. import type { Meta } from storybook/your-framework; import { Button } from ./Button; const meta { /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, } satisfies Metatypeof Button; export default meta;纯 JavaScriptJS/JSX项目则可以省略类型标注直接导出默认对象import { Button } from ./Button; export default { /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, };React 的 CSF Next 形态同样改用preview.meta(...)import preview from ../.storybook/preview; import { Button } from ./Button; const meta preview.meta({ /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, });import preview from ../.storybook/preview; import { Button } from ./Button; const meta preview.meta({ /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, });VueButton.stories.ts/Button.stories.jsVue 项目在 CSF 3 中同样使用Meta类型与default export此处以片段中最完整的 CSF Next 为例Vue 的 CSF 3 写法与上文「通用 CSF 3」完全一致CSF Next 则从.storybook/preview引入preview.metaimport preview from ../.storybook/preview; import Button from ./Button.vue; const meta preview.meta({ /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, });import preview from ../.storybook/preview; import Button from ./Button.vue; const meta preview.meta({ /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, });SvelteSvelte CSF 与 CSF 3 两种形态Svelte 有两种主流形态需按项目接入情况选择形态一Svelte CSF依赖storybook/addon-svelte-csf故事文件后缀为.stories.svelte在script module中使用defineMetascript module import { defineMeta } from storybook/addon-svelte-csf; import Button from ./Button.svelte; const { Story } defineMeta({ /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, }); /scriptscript module import { defineMeta } from storybook/addon-svelte-csf; import Button from ./Button.svelte; const { Story } defineMeta({ /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, }); /script形态二普通 CSF 3.stories.js/.stories.ts遵循通用 CSF 约定import Button from ./Button.svelte; export default { /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, };// Replace your-framework with svelte-vite or sveltekit import type { Meta } from storybook/your-framework; import Button from ./Button.svelte; const meta { /* The title prop is optional. * See docs/configure/user-interface/sidebar-and-urls.mdx#csf-30-auto-titles * to learn how to generate automatic titles */ title: Design System/Atoms/Button, component: Button, } satisfies Metatypeof Button; export default meta;Web Componentscomponent使用自定义元素名Web Components 渲染器有一个不同点component字段填的不是类组件而是自定义元素标签名例如demo-button。分组写法与其它框架一致export default { title: Design System/Atoms/Button, component: demo-button, };import type { Meta } from storybook/web-components-vite; const meta: Meta { title: Design System/Atoms/Button, component: demo-button, }; export default meta;其 CSF Next 形态同样通过preview.meta构造JS 与 TS 版本均如此import preview from ../.storybook/preview; const meta preview.meta({ title: Design System/Atoms/Button, component: demo-button, });import preview from ../.storybook/preview; const meta preview.meta({ title: Design System/Atoms/Button, component: demo-button, });两种 CSF 形态的等价性小结把上面的写法横向对比后可以看出分组本质只依赖一个信息传给title的斜杠路径字符串。形态差异仅在于承载方式形态承载位置适用场景CSF 3const meta { ... }后export default meta或用MetaT标注当前绝大多数项目的默认写法CSF Next试验import preview from ../.storybook/preview后const meta preview.meta({ ... })使用了新式 preview 对象与试验性配置的项目Svelte CSF.stories.svelte的script module中defineMeta({ ... })使用storybook/addon-svelte-csf的 Svelte 项目从 docs/_snippets/button-story-grouped.md 的源码片段可以看出官方为同一主题同时维护了「CSF 3」与「CSF Next 」两套代码片段用于在文档站点上按用户选定的框架与格式tabTitle渲染——这也是为什么同一个Design System/Atoms/Button会反复出现。你在自己的项目中只需按上文选择与项目技术栈匹配的一份即可。title是可选的显式分组与 CSF 3.0 自动标题的取舍分组片段中的注释反复提醒「The title prop is optional」。这是 Storybook 6.4 引入 CSF 3.0 之后的真实状态如果不写titleStorybook 会依据故事文件的物理磁盘位置自动推导标题auto-titles组件依然能在侧边栏中出现只是层级由文件路径决定。分组路径Design System/Atoms/Button与此并不冲突——它本质上只是「把自动推导结果中与文件路径对应的部分显式改写为符合设计系统语义的路径」。自动标题的推导逻辑可以在源码 code/core/src/shared/story-index/autoTitle.ts 中看到端倪userOrAutoTitleFromSpecifier会先检查文件是否命中 stories 配置importPathMatcher未提供userTitle时把「目录 titlePrefix 文件路径」拼接并做sanitize清洗autoTitle.ts#L49-L84。其中sanitizeautoTitle.ts#L12-L33处理了两种冗余情况文件名与所在目录同名例如components/MyComponent/MyComponent.stories.js会被折叠为Components/MyComponent而不是冗长的Components/MyComponent/MyComponent文件名是index.stories.js|ts时会去掉index段。因此在使用自动标题时遵循「文件名与目录同名」「以 index.stories 命名」等约定会直接改变侧边栏显示而当你需要精细控制分组例如把散落在不同目录下的组件归到同一个设计系统分组中、或者想保留某种不被自动标题启发式规则改写的命名时就应该显式写出title也就是本文Design System/Atoms/Button这种写法。关于自动标题的完整规则大小写保留、冗余文件名启发式、titlePrefix前缀、Story Indexers 索引机制等可以继续阅读 docs/configure/user-interface/sidebar-and-urls.mdx 中的 “CSF 3.0 auto-titles” 一节。分组之后Roots 的展示与关闭方式分组标题的第一个分段会成为侧边栏最顶层的「根节点」。按 docs/configure/user-interface/sidebar-and-urls.mdx 的说明默认情况下Storybook 会把最顶层的节点视为roots根在 UI 上以大写字样的「分区」呈现而不是普通文件夹顶层的下一级分组则以文件夹形式显示。上图截图中大写展示的DESIGN SYSTEM即是 root 的典型表现。如果你希望顶级节点也退化为普通文件夹可以在.storybook/manager.js中设置sidebar.showRoots: false。需要注意的是showRoots只影响「根节点是否以独立分区展示」并不会改变/分隔符本身划分出的层级数量。深层联动分组标题如何决定 Story 的 id 与 URL 链接title不只是 UI 上的分组标签它还与每个 Story 的稳定标识符绑定。按 docs/configure/user-interface/sidebar-and-urls.mdx 的说明Storybook 默认会基于组件标题与 Story 名称生成每个 Story 的id这个 id 会进入 URL 并可作为永久链接Permalink使用。例如某个标题为Foo/Bar、story 名为Baz的用例会被生成形如foo-bar--baz的 id对应链接为?path/story/foo-bar--baz。由此可以推断把标题写成Design System/Atoms/Button后该文件下每个 Story 的 id 前缀都会带上由该分组路径归一化出的哈希片段——这意味着调整分组结构会连带改变既有 Story 的 URL。文档给出的应对方案是在需要保留链接时手动为 Story 设置idStorybook 会优先使用显式id生成 URL其次才用title与story.name。在项目源码中这类 id 归一化工具集中在 code/core/src/csf/csf-utils.tstoId相关实现侧边栏与 URL 的完整配置选项可查阅 docs/configure/user-interface/sidebar-and-urls.mdx。小结与实践建议围绕Design System/Atoms/Button这一行核心代码可以把本文要点收敛为几条可直接落地的经验分组零成本任何 CSF 文件只要把title写成带/的路径如Design System/Atoms/ButtonStorybook 就会自动把相关组件归并进可展开的层级无需额外插件或配置。全框架同构Angular、React、Vue、Web Components、Svelte 在分组语义上完全一致唯一差别是meta的构造形态CSF 3 的export default meta、CSF Next 的preview.meta()、Svelte CSF 的defineMeta()。两种组织路径要分清显式title适合跨目录归拢组件、按设计系统语义命名隐式自动标题则适合「侧边栏镜像文件系统」的场景。对大规模 Storybook官方更推荐按文件层级为组件命名docs/configure/user-interface/sidebar-and-urls.mdx。分组会波及链接title参与 Story id 生成改动分组路径时若需保持 Permalink 稳定应使用显式id。边验证边调整改动title后重启或热更新 dev server即可在侧边栏实时看到分组折叠结果对照 docs/_assets/writing-stories/naming-hierarchy-with-path.png 的效果自查层级是否正确。需要继续深入时可回到本片段的上下文 docs/writing-stories/naming-components-and-hierarchy.mdx覆盖命名、分组、Roots、单 Story 提升与 storySort 排序并结合配对片段 docs/_snippets/checkbox-story-grouped.md 练习把多个组件归入同一分组。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门