Storybook Addon 面板开发:用 addons.add 与 types.PANEL 注册你的第一个 Addon Panel

发布时间:2026/9/9 12:44:11

Storybook Addon 面板开发:用 addons.add 与 types.PANEL 注册你的第一个 Addon Panel
Storybook Addon 面板开发用 addons.add 与 types.PANEL 注册你的第一个 Addon Panel【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook本篇技术指南聚焦于 Storybook 自定义 UI Addon 中最常见的一种形态——Addon Panel面板。文中以仓库 docs/_snippets/storybook-addon-panel-initial.md 给出的最小可运行示例为骨架逐步讲解如何借助storybook/manager-api的addons.register与addons.add、以及storybook/internal/components提供的AddonPanel组件把一个带标题、可切换激活态的页面注册进 Storybook 的底栏/侧栏面板区域。读完本文后你将能独立搭建一个最小面板 Addon并理解active属性、types.PANEL、ID 命名约定等关键概念为开发 a11y、themes、controls 这类官方生态中的复杂面板 Addon 打下基础。这个面板代码片段解决了什么问题在 Storybook 中用户看到的“Addons 面板”区域默认位于画布下方可通过配置挪到右侧是一个可扩展的容器。官方 Addon如 Actions、Controls、Accessibility都把各自的 UI 塞进这个区域以Tab 面板的形式呈现用户点击某个 Tab下方对应面板就会被激活显示。开发者在自己的 Addon 中想要拥有同样的能力只需完成两件事用addons.register()声明一个 Addon 的入口用addons.add()把当前 Addon 要渲染的“UI 单元”登记进去并声明其类型为types.PANEL。上述逻辑在 docs/addons/addons-api.mdx 中被归类为Core Addon API本片段即为该 API 中addons.add()一节的配套最小示例。其完整代码为import React from react; import { addons, types } from storybook/manager-api; import { AddonPanel } from storybook/internal/components; const ADDON_ID myaddon; const PANEL_ID ${ADDON_ID}/panel; addons.register(ADDON_ID, (api) { addons.add(PANEL_ID, { type: types.PANEL, title: My Addon, render: ({ active }) ( AddonPanel active{active} div Storybook addon panel /div /AddonPanel ), }); });这段代码就是面板 Addon 的“最小可行骨架”。把它放进 Addon 的 manager 入口文件例如 Addon Kit 模板中的src/manager.ts构建后在 Storybook 的 addons 面板区域就会多出一个名为My Addon的 Tab。接下来逐行拆解它的工作机制。面板的注册入口addons.register()addons.register()是所有 UI 型 Addon 的统一入口函数。它接收两个参数addonIdAddon 的唯一标识字符串全仓库/全生态内应保持唯一registrationCallback注册回调Storybook 在初始化管理器 UI 时会调用它并把当前 Storybook API 实例作为参数传入。addons.register(ADDON_ID, (api) { // 在这里通过 api 访问 Storybook APIselectStory、setQueryParams 等 // 并在此调用 addons.add() 注册本 Addon 的各种 UI 单元 });片段中ADDON_ID myaddon就是当前示例 Addon 的唯一名称。而(api)回调参数来自官方文档中反复强调的 Storybook API它提供了selectStory、setQueryParams、openInEditor、getCurrentStoryData、togglePanel等一系列方法与管理器 UI 交互详见 docs/addons/addons-api.mdx#storybook-api。在真实生态中Addon 命名常采用组织名/addon 名风格例如addons.register(my-organisation/my-addon, ...)见 storybook-addons-api-register.md。值得注意的是文档中storybook-addons-api-imports.md见 docs/_snippets/storybook-addons-api-imports.md明确区分了两个包的使用场景——与管理器 UI打交道的代码从storybook/manager-api导入而控制预览区行为的代码从storybook/preview-api导入。本片段导入的addons、types正来自storybook/manager-api因为它们操作的是管理器manager一侧的界面。登记面板addons.add() 与 types.PANEL在addons.register()回调内部紧接着调用addons.add(PANEL_ID, { ... })来登记 UI 单元。针对“面板”这种类型官方文档docs/addons/addons-api.mdx#addonsadd要求提供三个核心字段字段作用本片段取值type声明 UI 单元的类型panel / tool / tab 等决定它渲染在哪个区域types.PANELtitle显示在面板区域 Tab 上的标题My Addonrender渲染 Addon UI 组件的函数接收{ active }等参数({ active }) ...其中type取自storybook/manager-api暴露的types常量对象。把该字段设为types.PANEL即告诉 Storybook这个 UI 单元应该以“面板”的形式出现在 addons 区域并作为一个可点击的 Tab。关于render回调接收的参数docs/addons/addons-api.mdx 用一个信息提示框特别强调The render function is called withactive. Theactivevalue will be true when the panel is focused on the UI.也就是说当用户在 addons 区域点击并聚焦到当前面板的 Tab 时active为true切换到其他面板/隐藏面板时则为false。这是面板 Addon 必须处理的关键状态——它决定了面板内容何时真正渲染、何时执行副作用例如当面板失焦时暂停监听事件或释放资源。ID 命名约定PANEL_ID ${ADDON_ID}/panel片段中有两行容易被忽略但极其重要的常量const ADDON_ID myaddon; const PANEL_ID ${ADDON_ID}/panel;这是 Storybook 生态中的一种通用约定Addon 注册时使用一个基础 IDADDON_ID其下每类 UI 单元panel、tool、tab再各自派生出子 ID。派生方式通常是ADDON_ID / 单元类型例如面板myaddon/panel工具栏按钮myaddon/tool自定义 Tabmyaddon/tab这种分层命名能避免同一个 Addon 内不同单元之间、以及不同 Addon 之间产生 ID 冲突。如果你在写更复杂的 Addon同时含 toolbar 和 panel例如官方 a11y Addon通常会定义TOOL_ID ${ADDON_ID}/tool、PANEL_ID ${ADDON_ID}/panel并分别addons.add()。ID 还会被api.setConfig({ selectedPanel })见 docs/addons/addons-api.mdx 中的配置表格等 API 引用用来把某个面板设为默认选中项。AddonPanel 组件与 active 属性的配合render函数的返回值直接决定了面板区域的 UI。片段中使用了storybook/internal/components提供的AddonPanel容器组件AddonPanel active{active} div Storybook addon panel /div /AddonPanel把回调中解构出的active原样传给AddonPanel是标准用法。AddonPanel承担了面板外层容器Tab 页签切换后的内容承载区的职责active用来控制该面板内容区是否处于可见/激活状态避免未激活时仍挂载内容造成性能浪费或非预期副作用。仓库中的官方 Addon 也遵循同样的模式。以官方可访问性 Addon code/addons/a11y/src/manager.tsx 为例其核心注册代码如下addons.register(ADDON_ID, (api) { addons.add(PANEL_ID, { title: Title, type: types.PANEL, render: ({ active true }) ( A11yContextProvider{active ? A11YPanel / : null}/A11yContextProvider ), paramKey: PARAM_KEY, }); });可以看到官方实现同样由addons.registeraddons.addtype: types.PANEL 从render接收active组成并额外通过active ? A11YPanel / : null做条件渲染——这正体现了“面板激活才渲染内容”的推荐实践从源码结构看这种写法可以有效避免失焦面板持续占用 DOM 与计算资源。其单元测试见 code/addons/a11y/src/manager.test.tsx也通过断言注册对象中type api.types.PANEL来校验面板类型是否注册正确印证了types.PANEL在 API 层面的真实语义。在 addon-types 语境中定位面板 Addon在 Storybook 的 Addon 分类体系中详见 docs/addons/addon-types.mdx#panelsUI-based Addon 可渲染三类元素Panels面板在 addons 区域中显示自定义 UI是生态中最常见的 Addon 类型官方storybook/addon-a11y即采用此模式Toolbars工具栏向 Storybook 顶部工具栏添加自定义工具按钮Tabs自定义页签在画布区域新增独立 Tab。面板 Addon 的价值在于它能与当前选中的 story 联动展示组件状态、参数调试控件、测试结果、无障碍违规列表等“伴随性信息”。本文讨论的types.PANEL与AddonPanel组合正是支撑这类能力的核心载体。完整接入 Storybook 的落地方案要把上面的骨架片段真正跑起来你需要把它放置到 Addon 包中会被 Storybook manager 加载的入口文件里。结合 docs/addons/writing-addons.mdx 的说明落地的关键步骤与文件布局如下Addon 包结构在 Addon 源码目录典型如 Addon Kit 模板生成的my-addon/src/中维护 manager 侧代码。使用 TypeScript 时文件后缀为.ts使用 JavaScript 时后缀为.js——这正是片段头注filenamemy-addon/src/manager.js|ts的含义即该代码既可存为manager.ts也可存为manager.js。包内 React 版本约束由于面板直接渲染进 Storybook 的 manager UI带 UI 的 Addon 必须与 Storybook 使用相同的 React 版本见 docs/addons/writing-addons.mdx 中的提示。如果你的组件库使用不同 React 版本则不能把组件直接嵌进 manager 代码而应让 Addon 作为独立包发布、通过预览区通信来解耦。构建与发布Addon 在管理器与预览区运行环境不同需要产出不同 bundle。典型发布产物在package.json中以exports声明入口例如./manager: ./dist/manager.mjs并在bundler字段中列出managerEntries从而让 Storybook 正确加载这段 manager 代码完整字段可参考 docs/addons/writing-addons.mdx 中 Packaging 一节的示例。验证本地运行storybook dev后切换到任意 story观察 addons 区域是否出现标题为My Addon的 Tab点击它面板内容区应显示Storybook addon panel这段文字。从初始面板到完整 Addon 的进阶路线这段代码名为storybook-addon-panel-initial“initial初始”一词点明了它的定位——它只负责把面板“立起来”是一个可运行的起点。在此基础上继续演进通常会涉及以下能力均属 docs/addons/addons-api.mdx 的 API 范畴数据持久化与多单元协作使用useAddonStatehook 让面板状态跨 Storybook UI 生命周期保存例如记住上次的开关状态订阅事件通道通过addons.getChannel()或useChannel在管理器与预览 iframe 之间收发消息面板因此能实时反映当前 story 的运行状态读取当前 story 信息用api.getCurrentStoryData()或useParameter获取当前 story 的参数据此渲染与 story 强相关的面板内容控制面板可见性用api.togglePanel()编程式展开/收起整个 addons 面板区域设置默认选中面板通过api.setConfig({ selectedPanel: myaddon/panel })让 Storybook 启动时默认聚焦到本 Addon 的面板docs/addons/addons-api.mdx 中给出了storybook/actions/panel这类真实取值。在官方生态中从 A11y 面板展示无障碍违规列表、Controls 面板调试组件参数到测试相关面板本质上都是对本文骨架的扩展以types.PANEL挂载入口以active控制渲染时机再通过 manager/preview 之间的通道把数据灌入面板。掌握这段最小代码你就拿到了进入整个 Storybook Addon 生态的钥匙。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Hermes信使代理:从消息路由到多渠道通知分发的工程实践

Hermes信使代理:从消息路由到多渠道通知分发的工程实践

2026/9/9 12:44:11

1. 为什么我会动手写一个叫 Hermes 的信使代理如果你维护过两套以上的监控系统,或者同时对接过内部 OA、企业微信、钉钉和邮件告警,大概率遇到过这样的场景:每接一个系统,就要写一套新的通知逻辑。不是在这里拼 JSON,就…

让AI Agent亲手操作浏览器:ponytail Skill 实战指南

让AI Agent亲手操作浏览器:ponytail Skill 实战指南

2026/9/9 12:44:11

第一次看到 ponytail 这个名字的时候,我第一反应是:这年头连发型教程都开始上 GitHub 了?点进去翻了两眼才发现,这其实是个实打实的 Claude Skill,核心目标非常纯粹——让 AI Agent 能真正“操作浏览器”。它的作用一句…

Claude Code插件生态深度筛选:9款真正提升效率的生产力工具

Claude Code插件生态深度筛选:9款真正提升效率的生产力工具

2026/9/9 12:44:11

我用Claude Code这么长时间,感受最深的倒不是它本身能力有多强,而是周围的插件生态正在快速变成一个大杂烩。GitHub上随便一搜就是几十个号称“让你的Claude Code效能提升十倍”的仓库,装了几天发现,真正能用上的工具没几个&#…

Java Object类11个方法详解:从源码原理到实战应用

Java Object类11个方法详解:从源码原理到实战应用

2026/9/9 13:34:13

做Java开发这些年,我面试过不少候选人,也被人问过很多次“Object类有哪些方法”。这个问题看似基础,但它就像一面镜子,能照出一个人对Java语言底层设计到底理解到什么程度。毕竟Object是所有类的父类,Java里一切对象行…

Simulink异步电机定子匝间短路仿真建模全解析

Simulink异步电机定子匝间短路仿真建模全解析

2026/9/9 13:34:13

最近帮一个做电机故障诊断方向的朋友把定子匝间短路仿真的模型理了一遍,顺手把整套思路整理出来。这次要聊的是在Matlab Simulink环境下给感应电机(也就是异步电机)做定子匝间短路仿真的完整过程。电机故障诊断方向的同学和工程师应该都有印象…

构建生产级Agent基础设施:hermes-agent的设计与实践

构建生产级Agent基础设施:hermes-agent的设计与实践

2026/9/9 13:34:13

市面上的Agent框架不少,但真正拿到生产环境里用的时候,问题一堆:要么工具调用不可控,要么会话状态乱七八糟,要么出了问题根本没法排查。我自己在做一个内部客服机器人项目的时候,被这些问题折磨得够呛&…

会议室无线投屏全指南:从连接原理到故障排查与延迟优化

会议室无线投屏全指南:从连接原理到故障排查与延迟优化

2026/9/9 13:34:13

会议室里最常被打断的环节,往往不是方案本身,而是连接投影仪。笔记本找不到 HDMI 口、线材长度不够、手机里的内容没法快速展示、参会者轮流投屏时反复插拔,这些摩擦一旦出现在会议前几分钟,整个会议节奏都会被拖慢。把投影仪切换…

Firecracker 弃用功能全解析:DEPRECATED 清单、运行时告警机制与逐项迁移指南

Firecracker 弃用功能全解析:DEPRECATED 清单、运行时告警机制与逐项迁移指南

2026/9/9 13:34:13

Firecracker 弃用功能全解析:DEPRECATED 清单、运行时告警机制与逐项迁移指南 【免费下载链接】firecracker Secure and fast microVMs for serverless computing. 项目地址: https://gitcode.com/GitHub_Trending/fi/firecracker 本文基于 Firecracker 仓库根…

号码信息收集:用 PhoneInfoga 一次扫描查清号码的国家、运营商与网络足迹

号码信息收集:用 PhoneInfoga 一次扫描查清号码的国家、运营商与网络足迹

2026/9/9 13:24:13

号码信息收集:用 PhoneInfoga 一次扫描查清号码的国家、运营商与网络足迹 【免费下载链接】phoneinfoga Information gathering framework for phone numbers 项目地址: https://gitcode.com/GitHub_Trending/ph/phoneinfoga 当某个电话号码出现在可疑订单或…

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/9 1:14:29

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/8 4:55:53

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/8 22:37:26

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

2026/9/9 0:03:36

简介:面向毕业设计场景的PyQt5扩散模型图像恢复项目,提供完整Python源码与项目说明,适合图像处理、深度学习方向的高年级本科生与研究生参考。项目在模块设计上覆盖图像处理、扩散模型、参数配置、用户界面与结果评估五部分,具体涉…

开关电源环路裕量测试实战:相位裕量与增益裕量详解

开关电源环路裕量测试实战:相位裕量与增益裕量详解

2026/9/9 0:03:36

1. 项目概述:为什么环路裕量测试是电子工程师绕不开的“体检项目”“从零开始的电子工程师生活(6)——环路裕量测试”,这个标题一出来,老电源工程师可能已经下意识摸了摸示波器探头,新同事则大概率在想&…

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

2026/9/9 0:03:36

拆开市面上不同价位的定时插座,你会发现一个有意思的现象:有的里面躺着一颗黑色的软封装芯片,丝印都看不清;有的则是一块小小的蓝色或绿色PCB,上面赫然印着STM8或者STC的字样。同样叫"定时插座",…

远程协作的工作台整理

远程协作的工作台整理

2026/9/8 4:23:39

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/8 3:19:39

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/8 4:00:23

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…