加入直播:美国东部时间周四上午 11 点,Storybook 9 版本发布及 AMA
文档
Storybook Docs

自动文档和 Storybook

Storybook Autodocs 是一个强大的工具,可以帮助您快速为 UI 组件生成全面的文档。通过利用 Autodocs,您可以将 Stories 转换为动态文档,并且可以通过 MDX文档块 进一步扩展,以便清晰简洁地理解组件的功能。

Storybook 会推断出相关的元数据(例如 argsargTypesparameters),并自动生成一个文档页面,该页面及其信息位于侧边栏组件树的根级别。

Storybook autodocs

设置自动文档

Autodocs 通过 标签 配置。如果一个 CSF 文件包含至少一个带有 autodocs 标签的 Story,则会为该组件生成一个文档页面。

要为项目中的所有 Stories 启用自动文档,请将其添加到 .storybook/preview.js|ts 文件中的 tags

.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 = {
  // ...rest of preview
  //👇 Enables auto-generated documentation for all stories
  tags: ['autodocs'],
};
 
export default preview;

您也可以在组件(或 Story)级别启用它

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 = {
  component: Button,
  //👇 Enables auto-generated documentation for this component and includes all stories in this file
  tags: ['autodocs'],
} satisfies Meta<typeof Button>;
export default meta;

您可以通过删除标签来禁用特定组件的自动文档

Page.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 { Page } from './Page';
 
const meta = {
  component: Page,
  // 👇 Disable auto-generated documentation for this component
  tags: ['!autodocs'],
} satisfies Meta<typeof Page>;
export default meta;

同样,您可以通过删除标签,将特定 Story 从自动文档页面中排除

Button.stories.ts
// 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 = {
  component: Button,
  //👇 Enables auto-generated documentation for this component and includes all stories in this file
  tags: ['autodocs'],
} satisfies Meta<typeof Button>;
export default meta;
 
type Story = StoryObj<typeof meta>;
 
export const UndocumentedStory: Story = {
  // 👇 Removes this story from auto-generated documentation
  tags: ['!autodocs'],
};

配置

除了使用 tags 启用该功能外,您还可以扩展 Storybook 配置文件(即 .storybook/main.js|ts|cjs),并提供附加选项来控制文档的创建方式。以下是可用选项及其使用示例。

.storybook/main.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: ['@storybook/addon-docs'],
  docs: {
    //👇 See the table below for the list of supported options
    defaultName: 'Documentation',
  },
};
 
export default config;
选项描述
defaultName重命名自动生成的文档页面
默认值:docs: { defaultName: 'Documentation' }

编写自定义模板

要替换 Storybook 使用的默认文档模板,您可以扩展 UI 配置文件(即 .storybook/preview.js|ts),并引入一个 docs 参数。该参数接受一个返回 React 组件的 page 函数,您可以使用它来生成所需的模板。例如

.storybook/preview.tsx
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { Preview } from '@storybook/your-framework';
 
import {
  Title,
  Subtitle,
  Description,
  Primary,
  Controls,
  Stories,
} from '@storybook/addon-docs/blocks';
 
const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
    docs: {
      page: () => (
        <>
          <Title />
          <Subtitle />
          <Description />
          <Primary />
          <Controls />
          <Stories />
        </>
      ),
    },
  },
};
 
export default preview;

在内部,Storybook 使用类似的实现来生成默认模板。请参阅文档块 API 参考,了解有关文档块如何工作的更多信息。

更详细地介绍一下代码片段。当 Storybook 启动时,它将使用由以下部分组成的自定义模板覆盖默认模板

  1. 包含组件元数据的头部,这些元数据由 TitleSubtitleDescription 文档块检索。
  2. 文件中定义的第一个 Story,通过 Primary 文档块显示,并带有一组便捷的 UI 控件,用于放大和缩小组件。
  3. 一个交互式表格,包含 Story 中通过 Controls 文档块定义的所有相关的 argsargTypes
  4. 通过 Stories 文档块查看剩余的 Stories 概览。

使用 MDX

您还可以使用 MDX 生成文档模板。这在未配置 JSX 处理的非 React 项目中非常有用。通常,当您在项目中创建 MDX 文件时,它会被视为普通文档。要表明某个 MDX 文件是文档模板,请在其 Meta 文档块中提供 isTemplate 属性。例如

DocumentationTemplate.mdx
import { Meta, Title, Primary, Controls, Stories } from '@storybook/addon-docs/blocks';
 
{/*
  * 👇 The isTemplate property is required to tell Storybook that this is a template
  * See https://storybook.org.cn/docs/api/doc-blocks/doc-block-meta
  * to learn how to use
*/}
 
<Meta isTemplate />
 
<Title />
 
# Default implementation
 
<Primary />
 
## Inputs
 
The component accepts the following inputs (props):
 
<Controls />
 
---
 
## Additional variations
 
Listed below are additional variations of the component.
 
<Stories />

然后您可以在 .storybook/preview.js|ts 或通过导入它在单独的 Story 文件中使用它

.storybook/preview.jsx
import DocumentationTemplate from './DocumentationTemplate.mdx';
 
export default {
  parameters: {
    docs: {
      page: DocumentationTemplate,
    },
  },
};

如果您只需要覆盖单个组件的文档页面,我们建议创建一个 MDX 文件,并通过 <Meta of={} /> 文档块直接引用它。

生成目录

Storybook 自动生成的文档页面可能相当长且难以导航。为了解决这个问题,您可以启用目录功能,以提供文档页面的快速概览,并允许用户跳转到特定部分。要启用它,请扩展 Storybook UI 配置文件(即 .storybook/preview.js|ts),并提供一个带有 toc 属性的 docs 参数

.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: {
    docs: {
      toc: true, // 👈 Enables the table of contents
    },
  },
};
 
export default preview;

配置目录

默认情况下,文档页面的目录只会显示自动生成的 h3 标题。但是,如果您想自定义目录,可以向 toc 属性添加更多参数。以下是可用选项及其使用示例。

选项描述
contentsSelector定义搜索标题的容器 CSS 选择器
toc: { contentsSelector: '.sbdocs-content' }
disable隐藏文档页面的目录
toc: { disable: true }
headingSelector定义要在目录中显示的标题列表
toc: { headingSelector: 'h1, h2, h3' }
ignoreSelector配置目录以忽略特定的标题或 Stories。默认情况下,目录会忽略放置在 Story 块内的所有内容
toc: { ignoreSelector: '.docs-story h2' }
title定义目录的标题说明。
接受以下类型之一:stringnull、React element
toc: { title: 'Table of Contents' }
unsafeTocbotOptions提供附加的 TocBot 配置选项
toc: { unsafeTocbotOptions: { orderedList: true } }

contentsSelectorheadingSelectorignoreSelector 属性允许进行附加自定义。有关使用它们的更多信息,请参阅 Tocbot 文档

.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: {
    docs: {
      toc: {
        contentsSelector: '.sbdocs-content',
        headingSelector: 'h1, h2, h3',
        ignoreSelector: '#primary',
        title: 'Table of Contents',
        disable: false,
        unsafeTocbotOptions: {
          orderedList: false,
        },
      },
    },
  },
};
 
export default preview;

组件级配置

如果您想自定义特定 Story 的目录,可以在 Story 的默认导出中包含 toc 属性,并提供所需的配置。例如,如果您需要隐藏特定 Story 的目录,请按如下方式调整您的 Story

MyComponent.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 { MyComponent } from './MyComponent';
 
const meta = {
  component: MyComponent,
  tags: ['autodocs'],
  parameters: {
    docs: {
      toc: {
        disable: true, // 👈 Disables the table of contents
      },
    },
  },
} satisfies Meta<typeof MyComponent>;
 
export default meta;

自定义组件文档

使用 Storybook 的 Autodocs 创建自动化文档为您构建可持续的文档模式提供了起点。然而,它可能并非适用于所有情况,您可能希望对其进行扩展并提供更多信息。对于此类情况,我们建议结合使用 MDX 和 Storybook 的文档块来编写文档。

高级配置

记录多个组件

有时将多个组件一起记录很有帮助。例如,组件库的 ButtonGroup 和 Button 组件在没有彼此的情况下可能没有意义。

Autodocs 允许您记录通过 component 属性定义的“主”组件,以及一个或多个与其相关的 subcomponents

List.stories.ts|tsx
import React from 'react';
 
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { List } from './List';
import { ListItem } from './ListItem';
 
const meta = {
  component: List,
  subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent
} satisfies Meta<typeof List>;
export default meta;
 
type Story = StoryObj<typeof meta>;
 
export const Empty: Story = {};
 
export const OneItem: Story = {
  render: (args) => (
    <List {...args}>
      <ListItem />
    </List>
  ),
};

Subcomponents in ArgTypes doc block

主组件及其子组件将显示在 ArgTypes 文档块的标签页版本中。标签页标题将对应于 subcomponents 对象的键。

如果您想为组件组以不同的方式组织文档,我们建议使用 MDX。它让您可以完全控制组件的显示方式,并支持任何配置。

自定义文档容器

文档容器是包装文档页面的组件。它负责在 Storybook 的 UI 中渲染文档页面。您可以通过创建自己的组件并更新 Storybook UI 配置文件(即 .storybook/preview.js|ts)来引用它,从而对其进行自定义。

.storybook/preview.ts
import * as React from 'react';
 
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { Preview } from '@storybook/your-framework';
 
import { DocsContainer } from '@storybook/addon-docs/blocks';
 
const ExampleContainer = ({ children, ...props }) => {
  return <DocsContainer {...props}>{children}</DocsContainer>;
};
 
const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
    docs: {
      container: ExampleContainer,
    },
  },
};
 
export default preview;

覆盖默认主题

默认情况下,Storybook 为 UI 提供了两种主题:light(浅色)和 dark(深色)。如果您需要自定义文档使用的主题以匹配现有主题,可以更新 Storybook UI 配置文件(即 .storybook/preview.js|ts)并应用它。

.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';
 
import { themes, ensure } from 'storybook/theming';
 
const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
    docs: {
      theme: ensure(themes.dark), // The replacement theme to use
    },
  },
};
 
export default preview;

使用自定义 MDX 组件

开箱即用,Storybook 附带了一组可用于自定义文档页面的组件。如果您正在使用设计系统或组件库,并希望将它们添加到您的文档页面,则可以使用自己的组件覆盖从 @mdx-js/react 继承的 MDXProvider 组件。但是,这里有一个需要注意的地方,组件替换仅在您使用 Markdown 语法(例如,使用 # 表示标题)编写文档时生效。原生 HTML 元素,例如 <h1>,将不会被您的自定义实现替换。

.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';
 
import { MDXProvider } from '@mdx-js/react';
 
import { DocsContainer } from '@storybook/addon-docs/blocks';
 
import * as DesignSystem from 'your-design-system';
 
export const MyDocsContainer = (props) => (
  <MDXProvider
    components={{
      h1: DesignSystem.H1,
      h2: DesignSystem.H2,
    }}
  >
    <DocsContainer {...props} />
  </MDXProvider>
);
 
const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
    docs: {
      container: MyDocsContainer,
    },
  },
};
 
export default preview;

这不是 Storybook 的问题,而是 MDX 工作方式的细节。来自他们的迁移指南

“现在我们对组件进行‘沙盒化’处理,姑且这么称呼。这意味着当您传递一个用于 h1 的组件时,它确实会用于 # hi,但不会用于 <h1>hi</h1>

插件选项

文档插件接受选项以自定义文档页面的行为。您可以将它们添加到 Storybook UI 配置文件(即 .storybook/main.js|ts)中,作为注册插件的一部分。以下是可用选项

选项描述
csfPluginOptions为 Storybook 的 CSF 插件提供附加配置。可以使用 null 禁用。
mdxPluginOptionsMDX 文档提供附加配置选项和插件配置。

此示例演示如何应用这些选项。

.storybook/main.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    {
      name: '@storybook/addon-docs',
      options: {
        csfPluginOptions: null,
        mdxPluginOptions: {
          mdxCompileOptions: {
            remarkPlugins: [],
          },
        },
      },
    },
  ],
};
 
export default config;

故障排除

目录未按预期渲染

使用 Autodocs 的目录时,您可能会遇到目录显示与预期不同的情况。为了帮助您解决这些问题,我们整理了一些可能导致问题的场景列表。

对于简单的文档页面

如果您的文档页面只有一个匹配的标题并为其创建目录,目录将不会默认隐藏。解决此问题的一个潜在方法是添加第二个标题或完全关闭目录。

在小屏幕上

如果屏幕宽度小于 1200px,目录将默认隐藏。目前,没有内置解决方案可以解决此问题,同时又不影响文档页面的样式兼容性。

使用 MDX

如果您使用 MDX 编写未关联的文档,则无法自定义目录,这主要是由于当前实现不支持基于参数的定义。因此,目录将始终恢复为全局提供的默认配置

自动生成的文档在 monorepo 设置中不显示

开箱即用,Storybook 的 Autodocs 功能旨在自动为您的 Stories 生成文档。然而,如果您正在使用 monorepo 设置(例如 Yarn Workspacespnpm Workspaces),您可能会遇到部分文档未能生成的问题。为了帮助您排查这些问题,我们准备了一些建议,可能会对您有所帮助。

更新您的 import 语句,直接引用组件而不是包的根路径。例如

MyComponent.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';
 
// ❌ Don't use the package's index file to import the component.
// import { MyComponent } from '@component-package';
 
// ✅ Use the component's export to import it directly.
import { MyComponent } from '@component-package/src/MyComponent';
 
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: 'MyComponent',
  component: MyComponent,
} satisfies Meta<typeof MyComponent>;
 
export default meta;

此外,如果您正在使用 TypeScript 进行开发,您可能需要更新 Storybook 的配置文件(即 .storybook/main.js|ts)以包含以下内容

.storybook/main.ts
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  typescript: {
    // Overrides the default Typescript configuration to allow multi-package components to be documented via Autodocs.
    reactDocgen: 'react-docgen',
    check: false,
  },
};
 
export default config;

如果您仍然遇到问题,我们建议使用默认的沟通渠道(例如 GitHub discussion)联系社区。

在自动生成的文档中,控件未更新 Story

如果您通过 inline 配置选项关闭了 Stories 的内联渲染,您会遇到相关控件未能更新文档页面内 Story 的情况。这是当前实现的一个已知限制,将在未来的版本中解决。

了解更多关于 Storybook 文档的信息