Skip to main content
ClaudeWave
Skill62 repo starsupdated 6d ago

craft-garnish

Garnish — 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 (BaseDrag, DragSort, DragDrop, DragMove), form widgets (NiceText, CheckboxSelect, MixedInput, MultiFunctionBtn), utilities (key constants, ARIA helpers, focus management), and Craft integration (GarnishAsset, webpack externals, Craft.* class pattern). Triggers on: Garnish.Base.extend, Garnish.Modal, Garnish.HUD, Garnish.DragSort, Garnish.DisclosureMenu, Garnish.ESC_KEY/RETURN_KEY, activate/textchange events, UiLayerManager, registerShortcut, trapFocusWithin, garnishjs, GarnishAsset, CpAsset, CP JavaScript, modal dialog, HUD popover, Craft.CP, Craft.Slideout, Craft.ElementEditor, onSortChange, onOptionSelect, onSelectionChange, aria-modal, focus trap, keyboard navigation CP, this.base(), window.Garnish, CP memory leak, event listener cleanup, jQuery .on() in CP. Always use when writing, editing, or reviewing JavaScript that runs in the Craft CP — plugin CP assets, custom field type JS, element index JS, CP webpack config, or code that imports garnishjs or references window.Garnish. Also trigger for CP accessibility, keyboard interactions, drag-sort behavior, or CP JS memory issues. Do NOT trigger for front-end JavaScript (Alpine, Vue, htmx) or Twig templates (craft-site).

Install in Claude Code
Copy
git clone --depth 1 https://github.com/michtio/craftcms-claude-skills /tmp/craft-garnish && cp -r /tmp/craft-garnish/skills/craft-garnish ~/.claude/skills/craft-garnish
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Garnish — Craft CMS Control Panel JavaScript Toolkit

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.

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.

## Companion Skills — Load When Needed

- **`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.
- **`craft-php-guidelines`** — Load only when editing PHP files (asset bundle classes, controllers that register JS). Skip for pure JS work.

## Documentation

- Garnish source: `src/web/assets/garnish/src/` in the Craft CMS repository
- No official external documentation exists — this skill IS the documentation.

Use `WebFetch` on Craft's class reference (https://docs.craftcms.com/api/v5/) when looking up PHP-side asset bundle registration.

## Common Pitfalls (Cross-Cutting)

- Using jQuery `.on()` directly instead of `this.addListener()` — listeners added via jQuery won't auto-clean on `destroy()`, causing memory leaks.
- Forgetting `this.base()` when overriding `destroy()` — parent cleanup (listener removal, event teardown) gets skipped.
- Using `click` instead of `activate` event on non-`<button>` elements — `activate` handles both click and keyboard (Space/Enter), making the UI accessible.
- Fighting `UiLayerManager` by binding ESC directly — use `Garnish.uiLayerManager.registerShortcut(Garnish.ESC_KEY, callback)` so escape routes through the layer stack correctly.
- Magic key code numbers instead of `Garnish.ESC_KEY`, `Garnish.RETURN_KEY`, etc. — constants are self-documenting and consistent.
- Instantiating Garnish widgets before the DOM is ready — Garnish requires jQuery and all dependencies loaded first; in plugin assets, rely on `CpAsset` dependency chain.
- Not calling `destroy()` when removing widgets — orphaned listeners accumulate, especially in slideouts and live preview where DOM is repeatedly created/destroyed.
- 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.
- Using deprecated `Garnish.Menu` instead of `Garnish.CustomSelect` — `Menu` is an alias kept for BC only.
- 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.

## Reference Files

Read the relevant reference file(s) for your task. Multiple files often apply together.

**Task examples:**
- "Create a modal dialog in a plugin's CP JS" → read `class-system.md` + `ui-widgets.md`
- "Add drag-to-reorder to a custom field type" → read `drag-system.md` + `class-system.md`
- "Build a custom CP widget class" → read `class-system.md` + `integration.md`
- "Add a disclosure menu to a CP template" → read `ui-widgets.md` + `integration.md`
- "Handle keyboard events in CP JavaScript" → read `utilities.md` + `class-system.md`
- "Create an inline editor HUD" → read `ui-widgets.md` (HUD section)
- "Make a selection interface for elements" → read `ui-widgets.md` (Select section)
- "Set up a plugin's webpack config for Garnish" → read `integration.md`
- "Custom element index class isn't loading" → read `integration.md` (Element Index JS Loading)
- "Load element index JS with Vite" → read `integration.md` (Element Index JS Loading — Vite doesn't work for element index classes)
- "Add ARIA attributes to a custom modal" → read `utilities.md` (ARIA & Focus section)
- "Understand how Craft.CP extends Garnish" → read `integration.md` + `class-system.md`
- "Build a multi-state submit button" → read `integration.md` (Form Widgets section)
- "Add auto-growing textarea behavior" → read `integration.md` (Form Widgets section)

| Reference | Scope |
|-----------|-------|
| `references/class-system.md` | Garnish.Base, inheritance (extend/init/base), events (on/off/trigger), listeners (addListener/removeListener), settings, namespacing, enable/disable, destroy lifecycle |
| `references/ui-widgets.md` | Modal, HUD, DisclosureMenu, MenuBtn, SelectMenu, CustomSelect, ContextMenu, Select — constructor args, settings/defaults, methods, events, ARIA behavior |
| `references/drag-system.md` | BaseDrag, Drag, DragSort, DragDrop, DragMove — class hierarchy, settings/defaults, events, helper system, insertion points, scroll handling |
| `references/utilities.md` | Garnish namespace object, key constants, custom jQuery events (activate, textchange, resize), ARIA/focus management, geometry/hit testing, animation, form helpers, detection |
| `references/integration.md` | GarnishAsset PHP bundle, webpack externals, loading sequence, Craft.* class pattern, Twig JS blocks, form widgets (NiceText, CheckboxSelect, MultiFunctionBtn, MixedInput) |
craft-code-reviewer-deepSubagent

Deep code review on Opus 4.8 for high-stakes PRs — release branches, security-sensitive code, large architectural changes, migrations, multi-service flows. Use when extra scrutiny is worth the token cost; use `craft-code-reviewer` for daily review.

craft-code-reviewerSubagent

Reviews implemented code for quality, security, and Craft CMS conventions

craft-debuggerSubagent

Tracks down bugs in Craft CMS plugins with systematic investigation

craft-feature-builderSubagent

Builds new features in Craft CMS plugins following project architecture

craft-plannerSubagent

Breaks down large tasks into manageable implementation steps for Craft CMS plugin development

craft-site-builderSubagent

Builds Craft CMS site templates, components, and content architecture

craft-cloudSkill

Craft Cloud — Pixel & Tonic's serverless hosting platform for Craft CMS. Covers craft-cloud.yaml configuration, the Build → Migrate → Release deploy pipeline, the craftcms/cloud extension package, edge image transforms via Cloudflare, edge static caching with cache.rules + ESI, Cloud-managed S3 filesystem, MySQL 8 / Postgres 15 databases (no MariaDB, no tablePrefix), Console-based command runner and scheduled cron (once-per-hour minimum), auto-handled queue jobs, custom domains and SSL, preview environments per branch, Cloud limitations (ephemeral filesystem, no SSH, no .htaccess, no built-in mail), plugin development requirements for Cloud compatibility, and self-hosted → Cloud migration. Triggers on: craft-cloud.yaml, craftcms/cloud package, cloud.esi(), php craft cloud/up, php craft cloud/setup, App::isEphemeral(), CRAFT_EPHEMERAL, edge.craft.cloud, preview.craft.cloud, CRAFT_CLOUD_PROJECT_ID, CRAFT_CLOUD_ENVIRONMENT_ID, CRAFT_CLOUD_CDN_BASE_URL, Build → Migrate → Release, Cloud filesystem, Cloud-compatible plugin, Cloudflare Images at edge, AssetsFs, static-caching rules, ESI islands, deploy to Craft Cloud, migrate to Craft Cloud, self-hosted to Cloud, Craft Cloud quotas, Craft Cloud regions. Do NOT trigger for Servd (use the servd skill) or generic Craft deployment on Forge/bare metal (craftcms/deployment.md). Do NOT trigger for general DDEV local dev unrelated to Cloud parity.

craft-content-modelingSkill

Craft CMS 5 content modeling — sections, entry types, fields, Matrix, relations, project config, and content architecture strategy. Covers everything editors and developers need to structure content in Craft: choosing section types, designing entry types and field layouts, selecting field types for specific needs, configuring Matrix and nested entries, setting up relations and eager loading, and planning multi-site propagation. Triggers on: section types (single, channel, structure), entry types, field types, field layout design, field type selection, Matrix configuration, nested entries, relatedTo, eager loading, .with(), .eagerly(), categories, tags, globals, global sets, preloadSingles, propagation, multi-site content, URI format, project config, YAML, content architecture, content strategy, taxonomy, asset volumes, filesystems, image transforms, user groups, content permissions, entries-as-taxonomy, entrify, entrification, CKEditor vs Matrix, CMS editions, site propagation, multi-language, language groups, localization, translation method, field translation, content migration, reserved handles, field instances. Always use when planning content architecture, creating sections/fields, configuring Matrix, setting up relations, choosing field types, designing field layouts, making content modeling decisions, or planning multi-site content propagation. Do NOT trigger for PHP plugin/module development, custom field type code, front-end Twig templates, or buildchain configuration.