关于 craft-garnish
面向 Craft CMS 开发者的 Garnish 参考技能,涵盖其内置 JavaScript UI 框架。内容按任务组织,重点说明生命周期、无障碍支持和常见陷阱。
主要功能
- 01类系统与事件处理
- 02UI 和拖放组件
- 03无障碍与焦点工具
- 04Craft CP 集成指南
- 05按任务选择参考文档
适用场景
- 01实现模态框或展开菜单
- 02添加拖动排序交互
- 03处理键盘与 ARIA 行为
- 04在插件 JavaScript 中加载 Garnish
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ michtio/ craftcms-claude-skills --skill craft-garnish安装后在 Claude Code 中输入/craft-garnish确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/class-system.mddrag-system.mdintegration.mdui-widgets.mdutilities.md详细介绍
Garnish — Craft CMS 控制面板 JavaScript 工具包
Garnish 是 Craft CMS 内置的 JavaScript UI 框架,本参考涵盖其类系统、UI 控件、拖动交互、表单组件、无障碍辅助工具,以及与 Craft 控制面板(CP)的集成。
此技能仅涵盖 Garnish 本身——位于 src/web/assets/garnish/ 的 JavaScript 库。有关 PHP 端插件开发(元素、控制器、服务),请参阅 craftcms 技能。有关 Garnish 控件所依附的 CP 模板标记,请参阅 craftcms 技能中的 cp.md 参考。
配套技能——按需加载
craftcms— 当任务涉及 PHP 资源包类、插件架构或 Garnish 控件所依附的 CP 模板标记时加载。纯 JavaScript 重构、Garnish API 问题或仅涉及 JS 的任务无需加载。craft-php-guidelines— 仅在编辑 PHP 文件(资源包类、注册 JS 的控制器)时加载。纯 JS 工作无需加载。
文档
- Garnish 源码:Craft CMS 仓库中的
src/web/assets/garnish/src/ - 没有官方外部文档——本技能就是文档。
查找 PHP 端资源包注册信息时,请对 Craft 的类参考(https://docs.craftcms.com/api/v5/)使用 WebFetch。
常见陷阱(跨领域)
- 直接使用 jQuery
.on(),而不是this.addListener()——通过 jQuery 添加的监听器不会在destroy()时自动清理,可能导致内存泄漏。 - 重写
destroy()时忘记调用this.base()——这会跳过父类清理(移除监听器、拆除事件)。 - 在非
<button>元素上使用click事件,而不是activate事件——activate同时处理点击和键盘操作(空格键/回车键),让 UI 更易于访问。 - 直接绑定 ESC 来绕过
UiLayerManager——请使用Garnish.uiLayerManager.registerShortcut(Garnish.ESC_KEY, callback),让退出操作正确经过图层堆栈。 - 使用神奇的按键代码数字,而不是
Garnish.ESC_KEY、Garnish.RETURN_KEY等常量——常量更易读且更一致。 - 在 DOM 就绪前实例化 Garnish 控件——Garnish 要求先加载 jQuery 和所有依赖;在插件资源中,请依赖
CpAsset依赖链。 - 移除控件时不调用
destroy()——残留的监听器会不断累积,在滑出面板和实时预览中尤其如此,因为这些场景会反复创建和销毁 DOM。 - 将 Garnish 导入 webpack 包,而不是使用外部依赖——
import Garnish from 'garnishjs'会通过 webpack 外部依赖解析到window.Garnish;将其打包会多占用 134KB。 - 在注入到另一个表单的面板(条目编辑侧边栏面板、CP 模板钩子)中的输入框上添加
name属性——宿主表单会在保存时序列化这些输入框,导致插件的值被静默吞掉。输入框仅使用 id,JS 按 id 读取并提交到自有端点,并用 Enter 键保护逻辑防止宿主表单提交。请参阅integration.md(注入到另一个表单中的面板)。 - 使用已弃用的
Garnish.Menu,而不是Garnish.CustomSelect——Menu仅作为兼容旧版(BC)的别名保留。 - 使用已弃用的
Garnish.escManager或Garnish.shortcutManager,而不是Garnish.uiLayerManager——较新的管理器支持感知图层的键盘路由,并能遵循模态框/菜单堆栈。
参考文件
请阅读任务相关的参考文件。通常需要结合多个文件。
任务示例:
-“在插件的 CP JS 中创建模态对话框”→ 阅读 class-system.md + ui-widgets.md
-“为自定义字段类型添加拖动排序”→ 阅读 drag-system.md + class-system.md
-“构建自定义 CP 小部件类”→ 阅读 class-system.md + integration.md
-“在 CP 模板中添加展开菜单”→ 阅读 ui-widgets.md + integration.md
-“在 CP JavaScript 中处理键盘事件”→ 阅读 utilities.md + class-system.md
-“创建内联编辑器 HUD”→ 阅读 ui-widgets.md(HUD 部分)
-“为元素创建选择界面”→ 阅读 ui-widgets.md(Select 部分)
-“为 Garnish 设置插件的 webpack 配置”→ 阅读 integration.md
-“自定义元素索引类未加载”→ 阅读 integration.md(元素索引 JS 加载)
-“使用 Vite 加载元素索引 JS”→ 阅读 integration.md(元素索引 JS 加载 — Vite 不适用于元素索引类)
-“为自定义模态框添加 ARIA 属性”→ 阅读 utilities.md(ARIA 与焦点部分)
-“在 Garnish.Base 上构建自定义滑出面板/覆盖层/启动器”→ 阅读 ui-widgets.md(构建自定义覆盖层/滑出面板)+ class-system.md(启用/禁用)+ utilities.md(ARIA 与焦点)
-“我的启动器按钮只能用一次/出现‘Blocked aria-hidden’警告”→ 阅读 class-system.md(启用/禁用)+ utilities.md(关闭覆盖层:隐藏前将焦点移出)
-“了解 Craft.CP 如何扩展 Garnish”→ 阅读 integration.md + class-system.md
-“从插件向条目编辑屏幕的侧栏添加交互面板”→ 阅读 integration.md(注入到其他表单中的面板)+ craftcms 技能中的 cp-ui-patterns.md 以获取标记
-“保存条目后面板字段消失/按 Enter 键会提交条目表单”→ 阅读 integration.md(注入到其他表单中的面板)
-“构建多状态提交按钮”→ 阅读 integration.md(表单小部件部分)
-“添加自动扩展的文本区域行为”→ 阅读 integration.md(表单小部件部分)
| 参考文件 | 范围 |
|---|---|
references/class-system.md | Garnish.Base、继承(extend/init/base)、事件(on/off/trigger)、侦听器(addListener/removeListener)、设置、命名空间、启用/禁用、销毁生命周期 |
references/ui-widgets.md | Modal、HUD、DisclosureMenu、MenuBtn、SelectMenu、CustomSelect、ContextMenu、Select — 构造函数参数、设置/默认值、方法、事件、ARIA 行为 |
references/drag-system.md | BaseDrag、Drag、DragSort、DragDrop、DragMove — 类层次结构、设置/默认值、事件、辅助器系统、插入点、滚动处理 |
references/utilities.md | Garnish 命名空间对象、按键常量、自定义 jQuery 事件(activate、textchange、resize)、ARIA/焦点管理、几何/命中测试、动画、表单辅助函数、检测 |
references/integration.md | GarnishAsset PHP 包、webpack externals、加载顺序、Craft.* 类模式、Twig JS 区块、表单小部件(NiceText、CheckboxSelect、MultiFunctionBtn、MixedInput) |