文档
Storybook 文档

自动文档和 Storybook

观看视频教程

Storybook 自动文档是一个强大的工具,可以帮助您快速为 UI 组件生成全面的文档。通过利用自动文档,您将故事转变为活的文档,可以进一步扩展使用 MDX文档块 来提供对组件功能的清晰简洁的理解。

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

Storybook autodocs

设置自动文档

自动文档通过 标签 配置。如果 CSF 文件包含至少一个标记为 autodocs 的故事,则将为该组件生成一个文档页面。

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

.storybook/preview.ts
// Replace your-renderer with the renderer you are using (e.g., react, vue3)
import type { Preview } from '@storybook/your-renderer';
 
const preview: Preview = {
  // ...rest of preview
  //👇 Enables auto-generated documentation for all stories
  tags: ['autodocs'],
};
 
export default preview;

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

Button.stories.ts
// Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite)
import type { Meta } from '@storybook/your-framework';
 
import { Button } from './Button';
 
const meta: Meta<typeof Button> = {
  component: Button,
  //👇 Enables auto-generated documentation for this component and includes all stories in this file
  tags: ['autodocs'],
};
export default meta;

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

Page.stories.ts
// Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite)
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { Page } from './Page';
 
const meta: Meta<typeof Page> = {
  component: Page,
  // 👇 Disable auto-generated documentation for this component
  tags: ['!autodocs'],
};
export default meta;

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

Button.stories.ts
// Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite)
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { Button } from './Button';
 
const meta: Meta<typeof Button> = {
  component: Button,
  //👇 Enables auto-generated documentation for this component and includes all stories in this file
  tags: ['autodocs'],
};
export default meta;
 
type Story = StoryObj<typeof Button>;
 
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-webpack5, vue3-vite)
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-essentials'],
  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 参数。此参数接受一个 page 函数,该函数返回一个 React 组件,您可以使用它来生成所需的模板。例如

.storybook/preview.tsx
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { Preview } from '@storybook/your-framework';
 
import { Title, Subtitle, Description, Primary, Controls, Stories } from '@storybook/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. 文件中通过 Primary 文档块定义的第一个故事,以及一套方便的 UI 控件,用于放大和缩小组件。
  3. 一个交互式表格,其中包含通过 Controls 文档块定义的故事中所有相关的 argsargTypes
  4. 通过 Stories 文档块对剩余故事的概述。

使用 MDX

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

{/* DocumentationTemplate.mdx */}
 
import { Meta, Title, Primary, Controls, Stories } from '@storybook/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 或单个故事文件中通过导入它来使用它

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

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

生成目录

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

.storybook/preview.ts
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { 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配置目录以忽略特定标题或故事。默认情况下,目录将忽略放置在故事块中的所有内容
toc: { ignoreSelector: '.docs-story h2' }
title定义目录的标题说明文字。
接受以下之一:stringnull、React 元素
toc: { title: '目录' }
unsafeTocbotOptions提供其他 TocBot 配置选项
toc: { unsafeTocbotOptions: { orderedList: true } }

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

.storybook/preview.ts
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { 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;

组件级配置

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

MyComponent.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta } from '@storybook/your-framework';
 
import { MyComponent } from './MyComponent';
 
const meta: Meta<typeof MyComponent> = {
  component: MyComponent,
  tags: ['autodocs'],
  parameters: {
    docs: {
      toc: {
        disable: true, // 👈 Disables the table of contents
      },
    },
  },
};
 
export default meta;

自定义组件文档

使用 Storybook 的 Autodocs 创建自动文档,为您构建可持续文档模式提供了起点。但是,它可能不适合所有情况,您可能希望扩展它并提供其他信息。我们建议将 MDX 与 Storybook 的 文档块 结合使用,以解决此类情况并编写您的文档。

高级配置

记录多个组件

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

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

List.stories.ts|tsx
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
 
import { List } from './List';
import { ListItem } from './ListItem';
 
const meta: Meta<typeof List> = {
  component: List,
  subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent
};
export default meta;
 
type Story = StoryObj<typeof List>;
 
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)来引用它来自定义它。

.storybook/preview.ts
import * as React from 'react';
 
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { Preview } from '@storybook/your-framework';
 
import { DocsContainer } from '@storybook/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 提供两个主题:lightdark。如果您需要自定义文档使用的主题以匹配现有主题,您可以更新您的 Storybook UI 配置文件(例如,.storybook/preview.js)并应用它。

.storybook/preview.ts
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { 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, vue3)
import { Preview } from '@storybook/your-framework';
 
import { MDXProvider } from '@mdx-js/react';
 
import { DocsContainer } from '@storybook/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>

疑难解答

目录无法按预期呈现

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

使用简单的文档页面

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

使用小屏幕

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

使用 MDX

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

自动生成的文档没有在单仓库设置中显示

Storybook 的 Autodocs 功能开箱即用,旨在自动为您的故事生成文档。但是,如果您使用的是单仓库设置(例如,Yarn Workspacespnpm Workspaces),您可能会遇到部分文档无法为您生成的问题。为了帮助您解决这些问题,我们准备了一些可能对您有所帮助的建议。

更新您的导入语句,直接引用组件,而不是包的根目录。例如

MyComponent.stories.ts|tsx
// Replace your-framework with the name of your framework
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: Meta<typeof MyComponent> = {
  /* 👇 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,
};
 
export default meta;

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

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
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 讨论)联系社区。

控件没有更新自动生成的文档中的故事

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

详细了解 Storybook 文档

  • Autodocs 用于创建故事文档
  • MDX 用于自定义您的文档
  • Doc Blocks 用于编写您的文档
  • 发布文档 用于自动化发布文档的过程