文档
Storybook Docs

命名组件和层次结构

观看视频教程

Storybook 提供了一种强大的方式来组织你的 stories,为你提供了必要的工具,可以根据你组织的需要和偏好来分类、搜索和过滤你的 stories。

结构和层级

在组织 Storybook 时,有两种结构 stories 的方法:隐式显式隐式方法依赖于 stories 的物理位置将其放置在侧边栏中,而 显式方法则利用 title 参数来放置 story。

Storybook sidebar hierarchy

根据你的 Storybook 结构,你会发现 story 层级由各种部分组成

  • 类别:Storybook 生成 stories 和文档页面的顶层分组
  • 文件夹:一个中级组织单元,用于在侧边栏中对组件和 stories 进行分组,代表应用程序的一个功能或部分
  • 组件:一个低级组织单元,代表 story 正在测试的组件
  • 文档:组件的自动生成的 文档页面
  • Story:测试特定组件状态的单个 story

命名 stories

创建 stories 时,你可以显式使用 title 参数来定义 story 在侧边栏中的位置。它还可以用于 分组相关的组件,在一个可展开的界面中,以帮助 Storybook 组织,为用户提供更直观的体验。例如

Button.stories.ts
// 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 https://storybook.org.cn/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Button',
  component: Button,
} satisfies Meta<typeof Button>;
 
export default meta;

产生这个

Stories hierarchy without paths

分组

还可以将相关组件分组在一个可展开的界面中,以帮助 Storybook 组织。为此,请使用 / 作为分隔符

Button.stories.ts|tsx
// 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 https://storybook.org.cn/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Design System/Atoms/Button',
  component: Button,
} satisfies Meta<typeof Button>;
 
export default meta;
CheckBox.stories.ts|tsx
// 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 { CheckBox } from './Checkbox';
 
const meta = {
  /* 👇 The title prop is optional.
   * See https://storybook.org.cn/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Design System/Atoms/Checkbox',
  component: CheckBox,
} satisfies Meta<typeof CheckBox>;
 
export default meta;

产生这个

Stories hierarchy with paths

根节点

默认情况下,顶层分组将在 Storybook UI 中显示为“root”(即大写、不可展开的项)。如果你需要,可以 配置 Storybook 并禁用此行为。如果你需要为用户提供简化的体验,这会很有用;尽管如此,如果你有一个由多个组件 stories 组成的大型 Storybook,我们建议根据文件层级来命名你的组件。

单一 story 提升

单一 story 组件(即没有兄弟组件的组件 stories),其显示名称与组件名称(title 的最后一部分)完全匹配,会自动提升到 UI 中替换其父组件。例如

Button.stories.ts|tsx
// 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 as ButtonComponent } from './Button';
 
const meta = {
  /* 👇 The title prop is optional.
   * See https://storybook.org.cn/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Design System/Atoms/Button',
  component: ButtonComponent,
} satisfies Meta<typeof ButtonComponent>;
 
export default meta;
type Story = StoryObj<typeof meta>;
 
// This is the only named export in the file, and it matches the component name
export const Button: Story = {};

Stories hierarchy with single story hoisting

由于 story 导出会自动“首字母大写”(myStory 变为 "My Story"),你的组件名称应与之匹配。或者,你可以使用 myStory.storyName = '...' 来覆盖 story 名称,以匹配组件名称。

排序 stories

开箱即用,Storybook 根据 stories 的导入顺序对其进行排序。但是,你可以自定义此模式以满足你的需求,并通过在 preview.js 文件中的 options 参数中添加 storySort 来提供更直观的体验。

.storybook/preview.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      // The `a` and `b` arguments in this function have a type of `import('storybook/internal/types').IndexEntry`. Remember that the function is executed in a JavaScript environment, so use JSDoc for IntelliSense to introspect it.
      storySort: (a, b) =>
        a.id === b.id ? 0 : a.id.localeCompare(b.id, undefined, { numeric: true }),
    },
  },
};
 
export default preview;

除了唯一的 story 标识符之外,你还可以使用 titlename 和导入路径来使用 storySort 函数对你的 stories 进行排序。

storySort 也可以接受一个配置对象。

.storybook/preview.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      storySort: {
        method: '',
        order: [],
        locales: '',
      },
    },
  },
};
 
export default preview;
字段类型描述必需默认值示例
method字符串告诉 Storybook stories 的显示顺序Storybook 配置'alphabetical'
order数组要显示的 stories,按提供的名称排序空数组 []['Intro', 'Components']
includeNames布尔值在排序计算中包含 story 名称falsetrue
locales字符串需要显示的区域设置系统区域设置en-US

要按字母顺序对 stories 进行排序,请将 method 设置为 'alphabetical',并可选择设置 locales 字符串。要使用自定义列表对 stories 进行排序,请使用 order 数组;不匹配 order 列表中项目的 stories 将出现在列表项目之后。

order 数组可以接受一个嵌套数组来对二级 story 类型进行排序。例如

.storybook/preview.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      storySort: {
        order: ['Intro', 'Pages', ['Home', 'Login', 'Admin'], 'Components'],
      },
    },
  },
};
 
export default preview;

这将导致此 story 排序

  1. IntroIntro/* stories
  2. Pages story
  3. Pages/HomePages/Home/* stories
  4. Pages/LoginPages/Login/* stories
  5. Pages/AdminPages/Admin/* stories
  6. Pages/* stories
  7. ComponentsComponents/* stories
  8. 所有其他 stories

如果你想让特定类别排序到列表末尾,可以在 order 数组中插入一个 * 来指示“所有其他 stories”的位置

.storybook/preview.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      storySort: {
        order: ['Intro', 'Pages', ['Home', 'Login', 'Admin'], 'Components', '*', 'WIP'],
      },
    },
  },
};
 
export default preview;

在此示例中,WIP 类别将显示在列表的末尾。

请注意,order 选项独立于 method 选项;stories 首先按 order 数组排序,然后按 method: 'alphabetical' 或默认的 configure() 导入顺序排序。