📔 目录
🤔 我应该使用哪个徽章插件?
还有一些其他项目也用于在 Storybook 中显示徽章。本插件是 storybook-addon-badges(由 Jim Drury 开发)的重写版本,专注于利用 Storybook 的标签(tags)。我们将标签作为数据源来显示徽章,而不是使用专门的故事参数(story parameters),因为标签在 Storybook 中越来越普遍,并且与徽章的作用高度重叠。
这种架构选择开辟了新的可能性,但也导致原始插件的一些功能无法使用。下表总结了两个插件之间的差异。
storybook-addon-tag-badges | storybook-addon-badges | |
---|---|---|
在工具栏中显示徽章 | ✅ | ✅ |
在侧边栏中显示徽章 | ✅ | ⚠️ 仅针对当前故事 |
基于标签定义徽章 | ✅ | ❌ |
按故事自定义 | ❌ | ✅ |
工具提示支持 | ⚠️ 仅在工具栏中 | ✅ |
Storybook >= 8.4 | ✅ | ✅ |
Storybook < 8.3 | ❌ | ✅ |
[!NOTE] Storybook 8.5 需要 React 19。所有插件作者都必须采用 React 19 才能兼容 8.5。这就是为什么我的插件较新版本不再支持 Storybook 8.4 的原因。支持 Storybook 8.4 的最后一个版本是 v1.3.2。
📦 安装
yarn add -D storybook-addon-tag-badges
npm install -D storybook-addon-tag-badges
pnpm install -D storybook-addon-tag-badges
在你的 .storybook/main.ts
文件中,添加以下内容
// .storybook/main.ts
export default {
addons: ['storybook-addon-tag-badges'],
}
🏁 默认配置
此插件附带默认配置,你可以立即通过为内容添加标签来开始使用。
预配置徽章
预览 | 标签模式 | 建议用途 |
---|---|---|
![]() |
new |
最近添加的组件或属性/功能 |
![]() |
alpha , beta , rc , experimental |
警告组件或属性尚不稳定 |
![]() |
deprecated |
在新代码中应避免使用的组件或属性 |
![]() |
outdated |
设计已更改但尚未实现的组件,这可能会给用户带来额外的开发成本 |
![]() |
danger |
配置时需要特别注意的组件(例如,存在安全隐患的组件) |
![]() |
code-only |
仅存在于代码中而没有设计稿的组件 |
![]() |
version:* |
按组件版本控制 |
显示逻辑
默认情况下,所有标签始终显示在工具栏上,但只在侧边栏中显示给组件条目以及出现在顶层文档或故事条目。它们不会显示在组件或分组条目内部的文档或故事条目中。
此外,该插件在侧边栏中每个条目只显示一个徽章。配置中排在前面的徽章将优先显示。例如,new
徽章将显示在 code-only
徽章之前。
👀 用法
要显示预配置徽章,请将相关标签添加到你的组件、故事或文档条目中。
组件徽章
要为一个组件(及其子故事)设置徽章,请在该组件的 meta 中定义 tags
// src/components/Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'
const meta: Meta<typeof Button> = {
title: 'Example/Button',
component: Button,
tags: ['autodocs', 'version:1.0.0', 'new'],
}
故事徽章
要为特定故事添加徽章,请直接在故事对象中添加 tags
// src/components/Button.stories.ts
export const Tertiary: StoryObj<typeof Button> = {
args: {
variant: 'tertiary',
size: 'md',
},
tags: ['experimental'],
}
文档徽章
要为文档条目设置徽章,请将 tags
数组传递给 docs
参数
// src/components/Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'
const meta: Meta<typeof Button> = {
title: 'Example/Button',
component: Button,
parameters: {
docs: {
tags: ['outdated'],
},
},
}
🛠️ 自定义徽章配置
在你的 manager 文件中,你可以重新定义用于将标签映射到徽章的配置对象。每个标签只渲染一次,使用与其匹配的第一个徽章配置;因此,如果你也想保留默认配置,请务必将你的覆盖配置放在前面。
// .storybook/manager.ts
import { addons } from '@storybook/manager-api'
import {
defaultConfig,
type TagBadgeParameters,
} from 'storybook-addon-tag-badges'
addons.setConfig({
tagBadges: [
// Add an entry that matches 'frog' and displays a cool badge in the sidebar only
{
tags: 'frog',
badge: {
text: 'Frog 🐸',
bgColor: '#001c13',
fgColor: '#e0eb0b',
tooltip: 'This component can catch flies!',
},
display: {
sidebar: ['component'],
toolbar: false,
},
},
// Place the default config after your custom matchers.
...defaultConfig,
] satisfies TagBadgeParameters,
})
现在让我们详细了解 tagBadges
的各种属性。tagBadges
中的每个对象表示一个要匹配的标签列表,如果找到匹配项,则指定要使用的徽章配置以及徽章应该显示的位置。
标签
tags
属性定义了将显示徽章的标签模式。它可以是单个模式或模式数组。
标签模式可以是
模式类型 | 描述 | 示例模式 | 匹配结果 |
---|---|---|---|
string |
精确匹配 | 'new' |
'new' |
RegExp |
正则表达式 | /v\d+\d+\d+/ |
'v1.0.0' |
{ prefix: string | RegExp } |
匹配标签中 : 分隔符之前的部分 |
{ prefix: 'status' } |
'status:done' |
{ prefix: string | RegExp } |
匹配标签中 : 分隔符之后的部分 |
{ suffix: 'a11y' } |
'compliant:a11y' |
显示
display
属性控制徽章在哪里以及为哪种类型的内容渲染。它有两个子属性:sidebar
和 toolbar
。在侧边栏中,标签可以显示给组件、分组、文档或故事条目。在工具栏中,它们可以设置给文档或故事条目(因为其他条目类型不能在侧边栏外显示)。
Storybook 渲染以下条目类型
图标 | 名称 | 描述 |
---|---|---|
story | 在你的 CSF 文件中编写的组件故事之一。 | |
docs | 通过 MDX 文件或 autodocs 生成的文档页面。 | |
component | 一个组件的故事和 autodocs 页面的分组。 | |
group | 包含未附加的 MDX 文档、故事和/或组件的通用分组。 |
要控制徽章的显示位置,你可以向 sidebar
和 toolbar
键传递条件。你可以指定单个条件,或条件数组(在这种情况下,匹配任何一个条件都会导致徽章显示)。
条件可以指定你想显示徽章的条目类型,或者是否允许显示父条目(例如侧边栏中的顶层组件)未显示过的任何标签的徽章。在默认配置中,继承自父级的标签会被跳过;否则,当你将标签添加到 CSF meta 导出时,每个故事都会有一个标签,这将非常冗长。
一个条件完整形式有两个属性
属性 | 描述 | 类型 | 示例值 |
---|---|---|---|
type |
要匹配的条目类型 | string |
'docs' |
skipInherited |
如果 UI 中的父条目已经为同一个标签显示了徽章,是否跳过显示该徽章 | string |
true |
支持语法快捷方式,总结如下表
类型 | 描述 | 示例 | 侧边栏结果 | 工具栏结果 |
---|---|---|---|---|
ø (未设置) |
使用默认行为 | [{ skipInherited: true }, { type: 'component', skipInherited: false }, { type: 'group', skipInherited: false }] |
[{ type: 'docs' }, { type: 'story' }] |
|
false |
从不显示徽章 | false |
[] |
[] |
true |
在任何地方显示徽章 | true |
[{ skipInherited: false }] |
[{ type: 'docs' }, { type: 'story' }] |
string |
仅显示给一种条目类型,并跳过继承的标签徽章 | 'docs' |
[{ type: 'docs', skipInherited: true }] |
[{ type: 'docs' }] |
徽章
badge
属性定义了要显示的徽章的外观和内容。它可以是一个静态对象,也可以是一个根据匹配的内容和标签动态生成徽章的函数。
静态徽章对象
该对象具有以下属性
名称 | 类型 | 描述 | 示例 |
---|---|---|---|
text | string |
徽章中显示的文本(必需)。 | 'New' |
bgColor | string? |
传递给 background-color 的 CSS 属性。 |
'#aea黄绿色' |
fgColor | string? |
传递给 color 的 CSS 属性。 |
'#2f2' |
borderColor | string? |
边框颜色,渲染为 CSS box-shadow。 | '#2f2' |
tooltip | string | TooltipMessageProps? |
仅在工具栏中点击时显示的工具提示。 | 'This component is new!' 或 { title: 'New Component', desc: 'Recently added to the library' } |
动态徽章函数
动态徽章函数允许你根据当前条目和匹配的标签自定义徽章。它们必须返回如上所述的有效徽章对象。它们接收一个包含以下属性的对象参数
entry
: 当前的 HashEntry(组件、故事等),包含id
和/或name
、type
和tags
getTagParts
,getTagPrefix
,getTagSuffix
: 用于提取标签部分的实用函数tag
: 匹配的标签字符串
动态徽章函数示例
// .storybook/manager.ts
import { addons } from '@storybook/manager-api'
import {
defaultConfig,
type TagBadgeParameters,
} from 'storybook-addon-tag-badges'
addons.setConfig({
tagBadges: [
{
tags: { prefix: 'version' },
badge: ({ entry, getTagSuffix, tag }) => {
const version = getTagSuffix(tag)
const isUnstable = version.startsWith('0')
return {
text: `v${version}`,
bgColor: version.startsWith('0') ? '#f0ccff' : '#cce0ff',
tooltip: `Version ${version}${isUnstable ? ' (unstable)' : ''}`,
}
},
},
...defaultConfig,
] satisfies TagBadgeParameters,
})
工具提示
徽章在工具栏中显示时可能带有工具提示。为避免与侧边栏的功能冲突,侧边栏中禁用了工具提示,但欢迎对此提供反馈。
你可以为简单的工具提示传递一个字符串。你也可以传递 Storybook 的 TooltipMessage
使用的相同对象
title
: 工具提示的标题 [string]desc
: 工具提示的次要文本 [string]links
: 可选的链接对象数组,显示为按钮 [object[]]title
: 链接的标题href
: 链接指向的 URL(在当前位置导航)onClick
: 点击链接时的回调(可用于在新浏览器标签页中导航)
侧边栏配置
此插件使用 侧边栏 renderLabel
功能在侧边栏中显示徽章。如果你在 Storybook 实例中为其他目的定义了它,它将与此插件冲突,侧边栏徽章将不会显示。
要为未被你自己的 renderLabel
逻辑自定义的项显示徽章,你可以导入插件自己的 renderLabel
函数并在你的函数末尾调用它。
// .storybook/manager.ts
import { addons } from '@storybook/manager-api'
import type { API_HashEntry } from '@storybook/types'
import { renderLabel, Sidebar } from 'storybook-addon-tag-badges'
addons.setConfig({
sidebar: {
renderLabel: (item: API_HashEntry) => {
// Customise your own items, with no badge support.
if (item.name === 'Support') {
return '🛟 Get Support'
}
// Customise items with badge support by wrapping in Sidebar.
if (item.type === 'docs') {
return <Sidebar item={item}>{item.name} [doc]</Sidebar>
}
// Badges for every item not customised by you.
return renderLabel(item)
},
}
})
同样,如果你为 sidebar
选项定义配置但不包含 renderLabel
,则此插件定义的渲染函数将被覆盖,徽章将不会显示在侧边栏中。像这样导入并添加 renderLabel
函数
// .storybook/manager.ts
import { addons } from '@storybook/manager-api'
import { renderLabel } from 'storybook-addon-tag-badges'
addons.setConfig({
sidebar: {
/* your own changes here... */
renderLabel,
}
})
📝 工作流程示例
此仓库包含如何使用 Storybook 徽章支持各种工作流程的示例
- 市场细分
- 区分功能组件和品牌组件
- a11y、品牌、QA 等检查的合规状态
- 组件组合模式
- 使用外部依赖
- 智能组件
要查看这些示例的实际效果,请查看仓库并运行本地 Storybook 实例
git clone https://github.com/Sidnioulz/storybook-addon-tag-badges.git
cd storybook-addon-tag-badges
pnpm i
pnpm start
🐌 限制
按故事配置
此插件不支持更改特定故事的徽章配置,并且永远不会支持。这是因为 Storybook UI 的部分,例如侧边栏,是在未加载故事数据的上下文中渲染的。Storybook 在 v7 中停止预加载所有故事数据,以提高性能。
因此,我们需要在没有访问故事特定数据的情况下创建侧边栏标签。此插件使用 核心插件 API 读取你的配置,因此自定义特定徽章渲染的方式是使用动态徽章函数。这些函数可以利用故事的 ID、标题或标签内容来自定义渲染的徽章,如下面的示例所示。
组件标签
在 Storybook 中,你的 MDX 和 CSF 文件被转换为 docs
、component
、group
和 story
条目以渲染侧边栏,每个都有自己的语义。docs
和 story
条目分别直接继承 parameters.docs.tags
和 CSF meta
中定义的标签。
对于 component
条目,标签是间接计算的:它们是组件所有故事中存在的标签的交集。例如,对于在其 meta
中定义了标签 version:1.2.0
并且有一个故事定义了附加标签 deprecated
的组件,该组件条目将仅具有定义的 version:1.2.0
标签。
特别是,如果组件 meta
定义了两个标签 outdated
和 version:1.1.0
,但有一个故事明确移除了标签 outdated
(通过添加 !outdated
),则组件条目将仅具有标签 version:1.1.0
。
👩🏽💻 贡献
行为准则
请先阅读行为准则。
开发者来源证书
为确保贡献者在本项目许可条款下合法分享其贡献内容,贡献者必须遵守开发者来源证书 (DCO)。所有贡献都必须签名以满足 DCO。这由 Pull Request 检查处理。
通过签署你的提交,你证明以下内容
- 该贡献全部或部分由你创建,并且你有权在文件中指明的开源许可下提交它;或
- 该贡献基于以前的工作,据你所知,该工作受适当的开源许可覆盖,并且根据该许可,你有权在相同的开源许可下提交该工作及其修改(除非允许你在不同许可下提交),无论修改是全部还是部分由你创建,如文件中所示;或
- 该贡献由其他证明了第 1、2 或 3 条的人直接提供给你,并且你没有对其进行修改。
- 你理解并同意此项目和贡献是公开的,并且贡献记录(包括你随附提交的所有个人信息,包括你的签名)将无限期保留,并可能根据本项目或所涉及的开源许可进行再分发。
入门
本项目使用 PNPM 作为包管理器。
- 请参阅PNPM 安装说明
- 运行
pnpm i
常用命令
pnpm start
启动本地 Storybookpnpm build
构建并打包插件代码pnpm pack:local
生成一个本地 tarball,可在其他地方用作 NPM 依赖项pnpm test
运行单元测试
迁移到更高版本的 Storybook
如果你想迁移插件以支持最新版本的 Storybook,可以查阅插件迁移指南。
发布系统
此包通过 semantic-release 在推送到 main
分支时自动发布。不维护更新日志,并且 package.json
中的版本号不同步。
🆘 支持
请通过开一个 Issue 来提交 bug 报告或代码建议。请确保为 bug 报告包含一个可运行的最小工作示例 (Minimal Working Example)。你可以使用 storybook.new 来快速搭建一个复现环境。
✉️ 联系方式
Steve Dodier-Lazaro · Storybook Discord 上的 @Frog
- 领英 (LinkedIn)
项目链接:https://github.com/Sidnioulz/storybook-addon-tag-badges
💛 致谢
感谢
- 感谢Jim Drury 在原始徽章插件方面的开创性工作;我只是个模仿者
- 感谢Michael Shilman 在插件内部机制方面的帮助和他的反馈
- 感谢 Storybook addon kit 的所有贡献者