适用于 Web Components 的 Storybook 助手
[!WARNING] 此项目已迁移,现在可以在这里找到。
这些助手旨在简化 Web Components 与 Storybook 的集成。
这个助手库通过多种方式为开发者提供更好的 Storybook 和 Web Components 使用体验
- 利用类型提供更优的控件
- 防止 HTML 属性、JS 特性、插槽和 CSS Shadow Parts 名称冲突
- 提供带有 HTML 属性、JS 特性、CSS 自定义属性和 CSS Shadow Parts 绑定的模板。
- 提供模板中控件与组件属性的双向绑定,帮助控件值与组件保持同步
安装前
- 遵循Storybook 文档中的安装步骤
- 将您的自定义元素清单加载到 Storybook 的
preview.js
文件中
import { setCustomElementsManifest } from "@storybook/web-components";
import customElements from "./path/to/custom-elements.json";
setCustomElementsManifest(customElements);
- 将展开的控件添加到
preview.js
文件中的配置中
export const parameters = {
...
controls: {
expanded: true,
...
},
}
安装
npm i -D wc-storybook-helpers
设置
将 storybook 助手导入到您的 story 中
import { getWcStorybookHelpers } from "wc-storybook-helpers";
将元素的标签名称传递给 Storybook 助手函数。
const { events, args, argTypes, template } =
getWcStorybookHelpers("my-element");
将 argTypes
和 events
添加到您的 story 配置中
import type { Meta, StoryObj } from "@storybook/web-components";
const meta: Meta<MyElement> = {
title: "Components/My Element",
component: "my-element",
args,
argTypes,
parameters: {
actions: {
handles: events,
},
},
};
export default meta;
将模板添加到您的 story 模板中,并将 story 的 args
传递给 template
函数(这是一个可选参数,但要使参数正常工作则必需)
/**
* create Story type that will provide autocomplete and docs for `args`,
* but also allow for namespaced args like CSS Shadow Parts and Slots
*/
type Story = StoryObj<MyElement & typeof args>;
export const Default: Story = {
render: (args) => template(args),
args: {},
};
argTypes
根据自定义元素清单中的数据,助手将为您的参数应用适当的描述和控件类型。
控件类型
默认的控件类型并非总是最有帮助。助手将利用您的类型来尝试识别适合您控件的输入和选项。
例如,如果您的组件有一个名为 variant
的属性,带有预定义的值,助手会将其转换为一个选择框,该选择框会预先填充适当的值,并选中默认值。
带命名空间的控件
默认实现的一个挑战是,如果存在多个同名属性,它们会被覆盖。例如,如果有一个名为 label
的属性和一个名为 label
的插槽,只会显示其中一个。为了确保每个参数都能正确显示,CSS Shadow Part 和 Slot 参数将分别被加上后缀 -part
和 -slot
。CSS 自定义属性则不会被加上后缀,因为它们已经有唯一的属性值,而属性和特性将依赖于驼峰命名的特性名。
参考名称将与控件的描述一起记录。
然后可以使用该参考名称将默认值绑定到模板。
const DefaultTemplate = (args: any) => template(args);
export const Default: any = DefaultTemplate.bind({});
Default.args = {
docsHint: "Some other value than the default",
};
export const Default: Story = {
render: (args) => template(args),
args: {
docsHint: "Some other value than the default",
},
};
已废弃的控件
如果您在 jsDoc 描述中使用 @deprecated
标签,这些信息也会显示在描述中。
/**
* @deprecated replaced by `docs-hint`
* Copy for the read the docs hint.
*/
@property({ attribute: "old-docs-hint", reflect: true })
oldDocsHint = "Click on the Vite and Lit logos to learn more";
覆盖控件
如果您想更改任何控件,可以使用展开运算符(spread operator)轻松覆盖它,将更新的 argType
传入到助手的 argTypes
之后。
export default {
title: "Components/My Element",
component: "my-element",
argTypes: {
...argTypes,
docsHintAttr: {
name: 'docs-hint',
description: '...',
defaultValue: '...',
control: {
type: '...',
},
table: {
category: 'attributes',
defaultValue: {
summary: '...',
},
type: {
summary: '`string`',
},
},
},
...
};
事件
如果您想捕获组件输出的事件,可以在 story 配置的参数部分中进行映射。
注意: 只有当您的 CustomEvent
的 bubbles
选项设置为 true
时,它们才会被捕获(注意 - 默认为 true
)。
export default {
...
parameters: {
actions: {
handles: events,
},
},
};
如果您想将更多事件映射到您的 story 中,可以使用展开运算符(spread operator)扩展值。
export default {
...
parameters: {
actions: {
handles: [...events, 'my-other-event'],
},
},
};
Actions(操作)选项卡中的事件
如果您在 actions(操作)选项卡中没有看到事件显示,可能有以下两个原因之一
- 您的事件未配置为冒泡。
- 您的 Storybook 配置需要更新以包含
withActions
decorator。
// preview.js
import { withActions } from '@storybook/addon-actions/decorator';
const preview: Preview = {
parameters: {
controls: {
expanded: true,
sort: 'alpha'
},
},
decorators: [withActions],
};
模板
模板配置为自动将控件的 HTML 属性、JS 特性、CSS 自定义属性和 CSS Shadow Parts 映射到您的元素,并为组件属性提供双向数据绑定,以便与控件保持同步。
模板接受两个参数 - story 参数和插槽数据。您可以使用控件和 story 的 args
提供插槽数据,但如果您需要更精细的控制,可以在模板上使用 slot
参数,这将获得更多编辑器支持。
const SelectTemplate = (args: any) =>
template(
args,
html`
<span slot="label">My Select</span>
<my-option>Option 1</my-option>
<my-option>Option 2</my-option>
<my-option>Option 3</my-option>
`
);
export const Default: any = SelectTemplate.bind({});
Default.args = {
docsHint: "Some other value than the default",
};
扩展模板
组件模板可以插入到 story 的模板中,并带有额外的内容。
const FormTemplate = (args: any) => html`
<form>
${template(
args,
html`
<span slot="label">My Select</span>
<my-option>Option 1</my-option>
<my-option>Option 2</my-option>
<my-option>Option 3</my-option>
`
)}
<button>Submit</button>
</form>
`;
模板还暴露了一个名为 component
的变量,它引用了自定义元素,这样您就可以使用自定义逻辑。
const ComponentTemplate = (args: any) => html`
${template(
args,
html`
<span slot="label">My Select</span>
<my-option value="1">Option 1</my-option>
<my-option value="2">Option 2</my-option>
<my-option value="3">Option 3</my-option>
`
)}
<script>
// set property values
component.value = "2";
// call component methods
component.show();
</script>
`;
使用插槽控件
如果您正在使用 template
,使用控件面板的插槽非常直接。输入框已连接到相应的插槽,因此可以直接将富文本内容添加到输入框中,无需额外设置。
使用 CSS Shadow Parts 控件
与插槽控件类似,template
使处理 CSS Shadow Parts 变得容易。模板已预先配置了适当的代码,用于将样式应用到组件的部分。您可以直接将样式应用于控件输入框。
配置
助手包提供了一种方法,可以使用 setWcStorybookHelpersConfig
函数为您的 stories 设置全局配置。这可以添加到 .storybook/preview.js
文件中。
//preview.js
import { setWcStorybookHelpersConfig } from "wc-storybook-helpers";
setWcStorybookHelpersConfig({ ... });
setCustomElementsManifest(customElements);
助手可以接受以下选项
interface Options {
/** hides the `arg ref` label on each control */
hideArgRef?: boolean;
/** sets the custom type reference in the Custom Elements Manifest */
typeRef?: string;
/** Adds a <script> tag where a `component` variable will reference the story's component */
setComponentVariable: false,
/** renders default values for attributes and CSS properties */
renderDefaultValues: false,
}
隐藏“参数参考”
有时您可能想隐藏“参数参考”标签。您可以将 hideArgRef
设置为 true
,这将从控件中移除该标签。
setWcStorybookHelpersConfig({ hideArgRef: true });
使用 typeRef
的自定义类型
团队通常会解析或创建自定义类型,并将其添加到自定义元素清单中以供其他工具使用(如果您还没有这样做,CEM Analyzer Expanded Types plugin 可以提供帮助)。可以使用 typeRef
将助手配置为使用这些类型,而不是清单中的默认类型。如果找不到自定义类型,将回退到默认类型。
setWcStorybookHelpersConfig({ typeRef: "expandedType" });
添加组件变量
每个使用 template
助手的 story 都包含一个选项,可以添加一个 script 标签,其中在 component
变量中引用自定义元素。setComponentVariable
选项会添加此 script 标签和变量。
setWcStorybookHelpersConfig({ setComponentVariable: true });
渲染默认属性值
如果一个 arg
值与默认值匹配,它将不会添加到组件中。要始终显示属性和 CSS 自定义属性的默认值,请启用 renderDefaultValues
设置
setWcStorybookHelpersConfig({ renderDefaultValues: true });