$npx -y skills add michtio/craftcms-claude-skills --skill craft-garnishGarnish — Craft CMS's built-in JavaScript UI toolkit for the control panel. Covers the class system (Garnish.Base.extend, init, setSettings, addListener, on/off/trigger, destroy), UI widgets (Modal, HUD, DisclosureMenu, MenuBtn, CustomSelect, ContextMenu, Select), drag system (Ba
| 1 | # Garnish — Craft CMS Control Panel JavaScript Toolkit |
| 2 | |
| 3 | Reference for Garnish, Craft CMS's built-in JavaScript UI framework. Covers the class system, UI widgets, drag interactions, form components, accessibility helpers, and integration with Craft's CP. |
| 4 | |
| 5 | This skill is scoped to **Garnish itself** — the JavaScript library at `src/web/assets/garnish/`. For PHP-side plugin development (elements, controllers, services), see the `craftcms` skill. For CP template markup that Garnish widgets attach to, see the `craftcms` skill's `cp.md` reference. |
| 6 | |
| 7 | ## Companion Skills — Load When Needed |
| 8 | |
| 9 | - **`craftcms`** — Load when the task involves PHP asset bundle classes, plugin architecture, or CP template markup that Garnish widgets attach to. Skip for pure JavaScript refactoring, Garnish API questions, or JS-only tasks. |
| 10 | - **`craft-php-guidelines`** — Load only when editing PHP files (asset bundle classes, controllers that register JS). Skip for pure JS work. |
| 11 | |
| 12 | ## Documentation |
| 13 | |
| 14 | - Garnish source: `src/web/assets/garnish/src/` in the Craft CMS repository |
| 15 | - No official external documentation exists — this skill IS the documentation. |
| 16 | |
| 17 | Use `WebFetch` on Craft's class reference (https://docs.craftcms.com/api/v5/) when looking up PHP-side asset bundle registration. |
| 18 | |
| 19 | ## Common Pitfalls (Cross-Cutting) |
| 20 | |
| 21 | - Using jQuery `.on()` directly instead of `this.addListener()` — listeners added via jQuery won't auto-clean on `destroy()`, causing memory leaks. |
| 22 | - Forgetting `this.base()` when overriding `destroy()` — parent cleanup (listener removal, event teardown) gets skipped. |
| 23 | - Using `click` instead of `activate` event on non-`<button>` elements — `activate` handles both click and keyboard (Space/Enter), making the UI accessible. |
| 24 | - Fighting `UiLayerManager` by binding ESC directly — use `Garnish.uiLayerManager.registerShortcut(Garnish.ESC_KEY, callback)` so escape routes through the layer stack correctly. |
| 25 | - Magic key code numbers instead of `Garnish.ESC_KEY`, `Garnish.RETURN_KEY`, etc. — constants are self-documenting and consistent. |
| 26 | - Instantiating Garnish widgets before the DOM is ready — Garnish requires jQuery and all dependencies loaded first; in plugin assets, rely on `CpAsset` dependency chain. |
| 27 | - Not calling `destroy()` when removing widgets — orphaned listeners accumulate, especially in slideouts and live preview where DOM is repeatedly created/destroyed. |
| 28 | - Importing Garnish into webpack bundles instead of using the external — `import Garnish from 'garnishjs'` resolves to `window.Garnish` via webpack externals; bundling it duplicates 134KB. |
| 29 | - Using deprecated `Garnish.Menu` instead of `Garnish.CustomSelect` — `Menu` is an alias kept for BC only. |
| 30 | - Using deprecated `Garnish.escManager` or `Garnish.shortcutManager` instead of `Garnish.uiLayerManager` — the newer manager provides layer-aware keyboard routing that respects the modal/menu stack. |
| 31 | |
| 32 | ## Reference Files |
| 33 | |
| 34 | Read the relevant reference file(s) for your task. Multiple files often apply together. |
| 35 | |
| 36 | **Task examples:** |
| 37 | - "Create a modal dialog in a plugin's CP JS" → read `class-system.md` + `ui-widgets.md` |
| 38 | - "Add drag-to-reorder to a custom field type" → read `drag-system.md` + `class-system.md` |
| 39 | - "Build a custom CP widget class" → read `class-system.md` + `integration.md` |
| 40 | - "Add a disclosure menu to a CP template" → read `ui-widgets.md` + `integration.md` |
| 41 | - "Handle keyboard events in CP JavaScript" → read `utilities.md` + `class-system.m |