自动文档和 Storybook
Storybook Autodocs 是一个强大的工具,可以帮助您快速为 UI 组件生成全面的文档。通过利用 Autodocs,您可以将 Stories 转换为动态文档,并且可以通过 MDX 和 文档块 进一步扩展,以便清晰简洁地理解组件的功能。
Storybook 会推断出相关的元数据(例如 args
、argTypes
、parameters
),并自动生成一个文档页面,该页面及其信息位于侧边栏组件树的根级别。
设置自动文档
Autodocs 通过 标签 配置。如果一个 CSF 文件包含至少一个带有 autodocs
标签的 Story,则会为该组件生成一个文档页面。
要为项目中的所有 Stories 启用自动文档,请将其添加到 .storybook/preview.js|ts
文件中的 tags
中
// 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)级别启用它
// 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;
您可以通过删除标签来禁用特定组件的自动文档
// 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 从自动文档页面中排除
// 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
),并提供附加选项来控制文档的创建方式。以下是可用选项及其使用示例。
// 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
函数,您可以使用它来生成所需的模板。例如
// 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 启动时,它将使用由以下部分组成的自定义模板覆盖默认模板
- 包含组件元数据的头部,这些元数据由
Title
、Subtitle
和Description
文档块检索。 - 文件中定义的第一个 Story,通过
Primary
文档块显示,并带有一组便捷的 UI 控件,用于放大和缩小组件。 - 一个交互式表格,包含 Story 中通过
Controls
文档块定义的所有相关的args
和argTypes
。 - 通过
Stories
文档块查看剩余的 Stories 概览。
使用 MDX
您还可以使用 MDX 生成文档模板。这在未配置 JSX 处理的非 React 项目中非常有用。通常,当您在项目中创建 MDX 文件时,它会被视为普通文档。要表明某个 MDX 文件是文档模板,请在其 Meta
文档块中提供 isTemplate
属性。例如
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 文件中使用它
import DocumentationTemplate from './DocumentationTemplate.mdx';
export default {
parameters: {
docs: {
page: DocumentationTemplate,
},
},
};
如果您只需要覆盖单个组件的文档页面,我们建议创建一个 MDX 文件,并通过 <Meta of={} />
文档块直接引用它。
生成目录
Storybook 自动生成的文档页面可能相当长且难以导航。为了解决这个问题,您可以启用目录功能,以提供文档页面的快速概览,并允许用户跳转到特定部分。要启用它,请扩展 Storybook UI 配置文件(即 .storybook/preview.js|ts
),并提供一个带有 toc
属性的 docs
参数。
// 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 | 定义目录的标题说明。 接受以下类型之一: string 、null 、React elementtoc: { title: 'Table of Contents' } |
unsafeTocbotOptions | 提供附加的 TocBot 配置选项toc: { unsafeTocbotOptions: { orderedList: true } } |
contentsSelector
、headingSelector
和 ignoreSelector
属性允许进行附加自定义。有关使用它们的更多信息,请参阅 Tocbot
文档。
// 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
// 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
。
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>
),
};
主组件及其子组件将显示在 ArgTypes
文档块的标签页版本中。标签页标题将对应于 subcomponents
对象的键。
如果您想为组件组以不同的方式组织文档,我们建议使用 MDX。它让您可以完全控制组件的显示方式,并支持任何配置。
自定义文档容器
文档容器是包装文档页面的组件。它负责在 Storybook 的 UI 中渲染文档页面。您可以通过创建自己的组件并更新 Storybook UI 配置文件(即 .storybook/preview.js|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
)并应用它。
// 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>
,将不会被您的自定义实现替换。
// 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 禁用。 |
mdxPluginOptions | 为MDX 文档提供附加配置选项和插件配置。 |
此示例演示如何应用这些选项。
// 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 Workspaces
、pnpm Workspaces
),您可能会遇到部分文档未能生成的问题。为了帮助您排查这些问题,我们准备了一些建议,可能会对您有所帮助。
更新您的 import 语句,直接引用组件而不是包的根路径。例如
// 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
)以包含以下内容
// 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 文档的信息