
Component Story Format 3 现已推出
下一代故事格式,让您更具生产力

故事用于可视化组件在不同场景下的行为。组件故事格式 (CSF) 是故事的通用文件格式。
组件故事格式 3 (CSF3) 标志着故事的一次演进,它减少了样板代码并提高了人体工程学。这使得编写故事更加简洁和快速。
我很高兴地宣布 CSF3 的正式发布。在为期 18 个月的Beta测试期间,社区帮助我们发现了问题并改进了格式。从 Storybook 7 开始,CSF3 将成为编写故事的默认方式。
改进包括:
- ♻️ 可展开的故事对象,方便扩展故事
- 🌈 默认渲染函数,代码更简洁
- 📓 自动标题,更方便
- ▶️ 播放函数,用于脚本化交互和测试
- ✅ 与 CSF 2 完全向后兼容
请继续阅读,以了解有关该格式的更多信息,自最初发布以来发生了哪些变化,以及如何在 Storybook 7 中充分利用它。
等等,为什么?
在应用程序之外开发 UI 组件是创建高质量组件的最佳方式。Storybook 开创了这种组件驱动开发 (CDD) 风格。
现在,故事可用于设计人员和产品经理进行视觉审查,以及作为设计系统文档、自动化测试,甚至用于从生产组件生成设计资源。
难怪 Shopify、IBM 和 Salesforce 等许多全球最受欢迎的 UI 都是使用 Storybook 构建的。
CSF3 是故事的下一代演进——编写和维护更轻松
与前代产品类似,CSF3 基于 ESM。默认导出包含有关组件的信息,一个或多个命名导出(故事)捕获了不同的组件状态。主要区别在于,故事现在是对象,您可以为每个故事附加一个播放函数来模拟用户交互。
CSF3 与 CSF2 完全向后兼容,CSF2 在 Storybook 7 中仍然受支持。我们甚至已将播放函数移植到 CSF2。
我们建议迁移,因为 CSF3 更具表现力且更易于维护,需要更少的样板代码。在大多数情况下,您可以使用代码转换工具自动从 CSF 2 迁移到 CSF 3。

CSF3 功能回顾
大型项目可能包含数百个组件和数千个故事。当您编写如此多的故事时,人体工程学上的改进将带来显着的生活质量的提升。我们的目标是简化故事格式,使其更易于编写、阅读和维护。
让我们通过一个假设的 RegistrationForm 组件来看看 CSF3 的样子。
默认导出声明了您正在为其编写故事的组件
// RegistrationForm.stories.js
import { RegistrationForm } from './forms/RegistrationForm';
export default {
title: 'forms/RegistrationForm',
component: RegistrationForm,
};故事现在是对象
export const EmptyForm = {
render: (args) => <RegistrationForm {...args} />,
args: { /* ... */ },
parameters: { /* ... */ },
};
默认渲染函数,代码更简洁。 90% 的时间,编写故事只是以标准方式将一些输入传递给您的组件。
在 CSF3 中,如果您不指定渲染函数,每个故事都会渲染组件并传入所有参数。这大大简化了您的代码。
在我们的 RegistrationForm 示例中,渲染函数是样板代码
export const EmptyForm = {
// render: (args) => <RegistrationForm {...args} />, -- now optional!
args: { /* ... */ },
parameters: { /* ... */ },
};
可展开的故事对象,便于重用。当您尝试模拟复杂状态时,能够扩展现有故事而不是从头开始编写它们非常有用。假设您想展示已填写的表单,但在不同的视口下
export const FilledForm = {
args: {
email: 'marcus@acme.com',
password: 'j1287asbj2yi394jd',
}
};
export const FilledFormMobile = {
...FilledForm,
parameters: {
viewports: { default: 'mobile' }
},
};播放函数,用于脚本化交互。一些 UI 状态在没有用户交互的情况下是无法捕获的。播放函数在故事渲染后运行,并使用 testing-library 来模拟用户交互。例如
// RegistrationForm.stories.ts|tsx
import { userEvent, within } from '@storybook/testing-library';
// ...
export const FilledForm = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const emailInput = canvas.getByLabelText('email', {
selector: 'input'
});
await userEvent.type(emailInput, 'example-email@email.com', {
delay: 100
});
const passwordInput = canvas.getByLabelText('password', {
selector: 'input'
});
await userEvent.type(passwordInput, 'ExamplePassword', {
delay: 100
});
const submitButton = canvas.getByRole('button');
await userEvent.click(submitButton);
},
};
自动标题,更方便。在 CSF 中,故事的标题决定了它在 UI 中导航层级中的位置。在 CSF3 中,可以根据文件相对于根目录的位置自动生成标题。输入更少,并且在重新排序文件时无需更新。
export default {
// title: 'forms/RegistrationForm' -- optional
component: RegistrationForm,
};

有关 CSF3 功能和原理的深入描述,以及它与 CSF2 的确切区别,请参阅最初的 CSF3 文章。
对原版的修改
在过去的一年半里,用户一直在他们的项目中测试 CSF3。根据反馈,我们对原始版本进行了一些更改。
更好的 TypeScript 类型。我们更新了 7.0 中的 Meta/Story 类型,以支持故事的类型安全和自动完成。请继续关注我们即将发布的关于此内容的专门文章。
更新的自动标题启发式方法。Autotitle 根据 CSF 文件的磁盘位置生成“标题”(Storybook 侧边栏中的路径)。例如,如果 /project/path/src 是故事根目录,则 /project/path/src/atoms/Button.stories.js 的标题将是 atoms/Button。但是,朴素的启发式方法无法处理 atoms/Button/Button.stories.js 或 atoms/Button/index.stories.js 等常见模式。我们更新了启发式方法来处理这些情况。有关完整的迁移说明以及其他一些自动标题改进(包括更好的前缀处理和大小写),请参阅 MIGRATION.md。
更新了文档和 CLI 模板。最后但同样重要的是,我们使用 CSF3 源码片段更新了 7.0 的官方文档。我们还更新了 CLI,以便为新项目生成 CSF3。
立即升级到 CSF3
CSF3 完全向后兼容,因此您现有的 CSF 故事在不进行修改的情况下仍然可以正常工作。我们不会很快弃用旧格式。但是,CSF3 是一个重要的进步,我们建议您在升级到 Storybook 7.0 (SB7) 的同时升级您的故事。
要升级到 SB7,请参阅我们的 SB7 迁移指南。在项目升级后,您还可以使用以下代码转换工具将您的 CSF 故事迁移到 CSF3。请确保更新 glob 以包含您要更新的文件。
npx storybook@next migrate csf-2-to-3 --glob="**/*.stories.js"
如果您无法使用代码转换工具,我们还提供了升级说明。
参与进来
组件故事格式 (CSF) 帮助您单独开发、测试和记录您的组件。CSF3 改进了人体工程学,帮助您以更少的精力编写更多的故事。
CSF3 由 Michael Shilman(我!)、Kasper Peulen、Tom Coleman 和 Pavan Sunkara 开发,并得到了整个 Storybook 社区的测试和反馈。
Storybook 是由 1600 多名社区贡献者共同努力的成果。加入我们在 GitHub,或在 Discord 上与我们聊天。最后,请在 Twitter 上关注 @storybookjs 以获取最新消息。
组件故事格式 3 现已发布!
— Storybook (@storybookjs) 2023年1月26日
♻️ 可展开的故事对象
🌈 默认渲染函数
📓 自动标题
⏯️ 用于脚本化交互的播放函数
✅ 与 CSF 2 完全向后兼容
🗞️ 阅读所有相关信息... pic.twitter.com/TaMIKrTNV9